vue响应式原理
vue响应式原理
什么是响应式
vue最显著的特性之一便是不太引人注意的响应式系统(reactivity system)。
所谓的响应式,就是指模型层(model,只是普通 JavaScript 对象)发生变化了,就更新视图(view)
其实,就是前面提到的mvvm思想中来的单向数据绑定。
M,model发生了变化,那么我们的v,view随之更新。
典型的一些表现
- 更新data中的数据,当前组件的视图更新
- 更新data中的数据,计算属性也会更新
- 更新data中的数据,传递到子组件中的数据也会更新
表现1:组件视图的响应
表现2:计算属性的响应
表现3:子组件的响应式
效果:
是不是说,只要data代理的数据发生的变化,我们的视图就一定会更新呢?
答案是否定,请看如下案例:
效果如下:
说明,这种情况不具备响应式特点,为什么呢?
其原因和vue.js的响应式原理有关系的。
响应式原理(面试)
把一个普通 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
由于Object.defineProperty是es5中的方法,所以对于ie8及其以下的浏览器,vue.js是不支持的。
可以通过控制体查看这个信息:
每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
其图示如下:
这个模式,叫做观察者模式。
在这里,watcher监视data中代理的数据,一旦发生了变化,就会通知视图,进行更新操作。
为什么,刚才设置book的author属性,没有更新呢?
原因在于,book中并没有声明author属性,对应的就不存在getter和setters方法,所以,book中除name和price,其他任何的属性都没有列入观察的范围,所以就不具备响应特点。
基于这个响应式原理:受现代 JavaScript 的限制,Vue 不能检测到对象属性的添加或删除。
响应式细节
在使用vue.js来实现响应式,需要注意以下几点:
- Vue不允许动态添加根级响应式属性,所以你必须在初始化实例前声明根级响应式属性,哪怕只是一个空值
- 受现代JavaScript的限制,Vue不能检测到对象属性的添加或删除
- 数组直接修改索引也不能被检测到
- 可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上
- 还可以使用vm.$set实例方法,这也是全局 Vue.set 方法的别名
- 父组件的对象传递给子对象,在子对象中可以修改该对象
- Vue 异步执行 DOM 更新,为了在数据变化之后等待 Vue 完成更新 DOM,可以使用Vue.nextTick(callback)。
a.Vue不允许动态添加根级响应式属性,所以你必须在初始化实例前声明根级响应式属性,哪怕只是一个空值
如:
查看控制台如下:
b.受现代JavaScript的限制,Vue不能检测到对象属性的添加或删除,数组直接修改索引也不能被检测到
这个不会效果。
Vue.js提供了两种方式:
- 可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上
- 还可以使用vm.$set实例方法,这也是全局 Vue.set 方法的别名
使用set,编写代码如下:
测试,ok。
针对数组,使用索引来修改,也不会有响应特点。
点击,不会发生变化,如下:
也是可以使用set来进行修改,如下:
效果如下:
c.父组件的对象传递给子对象,在子组件中可以修改该对象
在子组件中,修改传递的基本类型数据,是不允许的,如下:
如果是对象类型呢?
修改如下:
实际上,由于对象在传递的时候,是传递的地址,父子组件中的对象是指同一个对象。
所以,在子组件中,是可以去修改父组件传递过来的对象。
vue.sync
vue .sync 修饰符以前存在于vue1.0版本里,但是在在 2.0 中移除了 .sync 。 2.3.0 又重新引入了 .sync 修饰符。只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on 监听器。
实际上,当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件:
this.$emit('update:foo', newValue)
vue 修饰符sync的功能是:当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定。如果不用.sync,也可以props传初始值,然后事件监听,实现起来也不算复杂。
d.Vue 异步执行 DOM 更新,为了在数据变化之后等待 Vue 完成更新 DOM。可以使用Vue.nextTick(callback)。
在vue.js中,model的变化,会导致视图发生更新,所谓视图更新,说白了,就是指dom更新。
但是,不要简单的认为这个更新操作是立刻完成。实际上,它是后续才完成的。
看着页面是发生变化了,变化的时刻并不是修改完数据的那一刻。
编写代码如下:
测试,如下:
说明,并不是一修改完这个msg,就立刻更新视图了。在vue.js中,它其实是进行了异步的更新操作。当前这种情况下,我们是无法在modify的操作中,获取更新之后的值。所以,针对这种情况,vue.js提供了一个nextTick的回调方法。
可以修改代码如下:
转载自:https://juejin.cn/post/7360645821137092623