Vue 双向绑定原理分析
Vue 双向绑定原理分析
首先我们为每个vue属性用Object.defineProperty()实现数据劫持,为每个属性分配一个订阅者集合的管理数组dep;然后在编译的时候在该属性的数组dep中添加订阅者,v-model会添加一个订阅者,{{}}也会,v-bind也会,只要用到该属性的指令理论上都会,接着为input会添加监听事件,修改值就会为该属性赋值,触发该属性的set方法,在set方法内通知订阅者数组dep,订阅者数组循环调用各订阅者的update方法更新视图。
一、数据变页面变
1.页面一定会变吗?什么情况下不会变?怎么解决?
首先,数据变页面不一定会变。以下情况不会变:
- 情况一、Vue只兼容IE8以上的版本,view层改变是基于Vue底层的Object.difineProtery 和getter ,setter,而IE8及以下浏览器没有这些属性,所以根本无法改变view层。
- 情况二、当给对象 动态添加一个属性(data中没有该属性),所以添加的属性没有getter和setter,
- 情况三、数组 动态修改数组的length相关,数据的修改也不会引起页面的变化
综上,页面没有实现双向绑定最主要的原因是没有setter和getter。在生命周期的创建阶段,vue会用object.definePropty 将data 里的数据进行处理,处理完成就拥有了setter和getter
二、用js实现简单的双向绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <input type="text" onkeydown="inputChange(this)"> <span></span> </body> <script> /* input 框里的数据发生改变后页面自动变 on: 1.处理数据有setter和getter 2.数据改变 触发set 3.set 通知watcher监听 4.watcher监听更新页面 */ let data={ inputValue:'' } let middle='' Object.defineProperty(data,'inputValue',{ get(){ return middle }, set(param){ middle=param watcher() } }) function inputChange(e){ // console.log(e) data.inputValue=e.value } function watcher(){ // 根据修改后的数据控制页面刷新 let value=data.inputValue document.getElementsByTagName('span')[0].innerHTML=value } </script> </html>
三、Vue如何实现
原理图:
-
3.1 observer用来实现对每个vue中的data中定义的属性循环用Object.defineProperty()实现数据劫持,以便利用其中的setter和getter,然后通知订阅者,订阅者会触发它的update方法,对视图进行更新。
-
3.2 我们介绍为什么要订阅者,在vue中v-model,v-name,{{}}等都可以对数据进行显示,也就是说假如一个属性都通过这三个指令了,那么每当这个属性改变的时候,相应的这个三个指令的html视图也必须改变,于是vue中就是每当有这样的可能用到双向绑定的指令,就在一个Dep中增加一个订阅者,其订阅者只是更新自己的指令对应的数据,也就是v-model='name’和{{name}}有两个对应的订阅者,各自管理自己的地方。每当属性的set方法触发,就循环更新Dep中的订阅者。
四、如何解决
- 法一、对于为创建的实例:将property 写在 data 对象中
- 法二、对于已经创建的实例:可以使用 Vue.set(object, propertyName, value) 或 vm.$set 实例方法方法向嵌套对象添加响应式 property
eg:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="app"> {{info.age}} <hr> {{info.name}} <button @click='add' >add</button> <button @click='change'>change</button> </div> </body> <script src="./Week3_VueS/day02/myapp/node_modules/vue/dist/vue.js"></script> <script> const vm=new Vue({ el:"#app", data:{ info:{ age:1 } }, methods:{ add(){ this.info.age++ console.log(this) }, change(){ // this.info.name='hehe' this.$set(this.info,'name','hehe') // console.log(this) } } }) </script> </html>
五、总结
首先我们为每个vue属性用Object.defineProperty()实现数据劫持,为每个属性分配一个订阅者集合的管理数组dep;然后在编译的时候在该属性的数组dep中添加订阅者,v-model会添加一个订阅者,{{}}也会,v-bind也会,只要用到该属性的指令理论上都会,接着为input会添加监听事件,修改值就会为该属性赋值,触发该属性的set方法,在set方法内通知订阅者数组dep,订阅者数组循环调用各订阅者的update方法更新视图。
- 浅谈vue,angular,react数据双向绑定原理分析
- Vue 双向数据绑定原理分析
- vue开发:vue,angular,react数据双向绑定原理分析
- 浅谈vue双向绑定原理分析图
- Vue双向数据绑定原理分析
- vue双向绑定的原理及实现双向绑定MVVM源码分析
- VUE双向数据绑定原理分析
- Vue 双向数据绑定原理分析
- Vue数据双向绑定原理和代码分析
- vue双向绑定原理分析
- Vue 双向数据绑定原理分析
- Vue 2.3.4源码分析之双向绑定原理
- Vue 双向数据绑定原理分析 以及 Object.defineproperty语法
- vue双向数据绑定原理
- Vue原理&实现双向绑定MVVM
- Vue 数据双向绑定原理
- 【vue】vue数据双向绑定实现原理
- 转-Vue双向绑定的原理
- Vue双向数据绑定实现原理
- vue数据双向绑定实现原理