vue的优点
1.数据的双向绑定,
展开: 数据劫持结合发布订阅模式,当数据发生变化啦,有observer观察者,内部采用Object.defineProperty的getter和setter来实现,观察到了数据的变化,然后通知dep消息订阅器,内部通过notify函数来触发相对应的watcher ,然后update更新视图。还有compile解析指令,解析数据初始化数据,渲染页面。****
Observer :数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者,内部采用Object.defineProperty的getter和setter来实现
Compile :指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
Watcher :订阅者,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数
Dep :消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法
当数据发生变化时,Observer 中的 setter 方法被触发,setter 会立即调用Dep.notify(),Dep 开始遍历所有的订阅者,并调用订阅者的 update 方法,订阅者收到通知后对视图进行相应的更新。
数据劫持:使用了Object.defineProperty(参数1,参数2,参数3)的方法对数据的进行劫持。参数1为对象, 参数2为属性, 参数3为描述符(分为数据描述符和存取描述符,二者一),vue的数据劫持为存取描述符,读取数据用get,该方法返回值被用作属性值。修改数据用set方法,该方法将接受唯一参数,并将该参数的新值分配给该属性。
数据描述符有四个属性: value为属性值。configurable: 仅当该属性的 configurable 为 true 时,该属性才能够被删除。默认为 false。仅当该属性的 writable 为 true 时,该属性才能够被修改。默认为 false。仅当该属性的 enumberable 为 true 时,该属性才能够被枚举。可以用for in 方法。默认为 false
- 组件化 (减少代码量, 可以提高效率和复用率)
3 虚拟dom(将模版转换成渲染函数(render),执行渲染函数就可以得到一个虚拟DOM,在得到真实dom)
展开:当数据发生变化,会重新构造一颗虚拟的dom树,然后比较新旧的差异,然后记录差异,把差异渲染到真实的dom树上。(采用深度优先遍历,把树形结构按照层级分解,只比较同级元素;当数据发生改变时,set方法会让调用Dep.notify通知所有订阅者Watcher,订阅者就会调用patch给真实的DOM打补丁(两个重要函数patchVnode和updateChildren))
diff算法比较后,会出现3种情况
1-1 如果新虚拟DOM找到了与旧虚拟DOM相同的key,但新旧虚拟DOM内容没有变,新的虚拟DOM就不用创建真实DOM,直接复用之前旧虚拟DOM创建的真实DOM。
1-2:如果新虚拟DOM找到了与旧虚拟DOM相同的key,但新旧虚拟DOM内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
1-3:如果新虚拟DOM中未找到与旧虚拟DOM相同的key,则创建新的真实DOM,随后渲染到页面
vue的缺点
1.当vue实例化后,新增的属性,是检测不到的,只有在data定义中才能检测到,但是给了解决办法** vue.set**
2.当通过index来改变数组也是监测不到数据的变化。vue给了7种方法** push pop shift unshift splice sort reserve **方法。还有可以通过vue.set也可以。vue.set(arr, index,value)
3. 必须遍历每一个属性来进行监听
proxy 代理(与reflect结合,来实现数据劫持)
拓展: var proxy = new Proxy(target,handler) taregt为目标对象, handler为配置对象(里面有很多方法)
1.get(target,propkey)
2 deleteProperty(target,propkey)
3 set(target, propkey, value)