Vue 数据响应式详解

前言

Vue最具特色的一点,就是数据驱动,即你不用写复杂的DOM操作,只需专心于业务所用到的数据。
那么,Vue的数据响应式到底是怎么实现的呢?

正文

数据变化的过程
  • 侦测数据的变化 (数据劫持 / 数据代理)
  • 收集视图依赖了哪些数据 (依赖收集)
  • 数据变化时,自动“通知”需要更新的视图部分,并进行更新 (发布订阅模式)
追踪数据

new Vue() 后, Vue 会调用 _init 函数进行初始化,也就是init 过程,在 这个过程Data通过Observer转换成了getter/setter的形式,来对数据追踪变化,当被设置的对象被读取的时候会执行getter函数,而在当被赋值的时候会执行setter函数。

  • 也就是说,当创建Vue实例时,Vue会将这个实例的data对象转换成getter/setter形式,这对用户是不可见的。
  • 所以就出现了无法进入响应式系统的数据,稍后介绍。
收集依赖

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据property记录为依赖。之后当依赖项的 setter触发时,会通知watcher,从而使它关联的组件重新渲染。

  • 当外界通过Watcher读取数据时,会触发getter从而将Watcher添加到依赖中。
订阅者

主要作用是用来存放 Watcher观察者对象

class Dep {
    constructor () {
        /* 用来存放Watcher对象的数组 */
        this.subs = [];
    }
    /* 在subs中添加一个Watcher对象 */
    addSub (sub) {
        this.subs.push(sub);
    }
    /* 通知所有Watcher对象更新视图 */
    notify () {
        this.subs.forEach((sub) => {
            sub.update();
        })
    }
}
  • 在修改对象的值的时候,会触发对应的settersetter通知之前依赖收集得到的 Dep 中的每一个 Watcher,告诉它们自己的值改变了,需要重新渲染视图。这时候这些Watcher就会开始调用update来更新视图。
    在这里插入图片描述
图解全过程

在这里插入图片描述

响应式注意项
  • 对于对象来说
    • 添加或者删除属性,那么这个属性是无法进入响应式系统的
    • 覆盖对象是可以进入响应式系统的
    • 解决方法可以用Vue.set()或是他的别名$set()
const app = new Vue({
        el: '#app',
        data: {}
    })
    
app.msg = 'hello' //不是响应式
app.$set(app, 'msg', 'hello') //响应式
  • 对于数组来说
    • 改变数组的长度
    • 根据索引值直接赋值
const app = new Vue({
    el: '#app',
    data: {
        arr: [1, 2, 3, 4]
    }
})

app.arr[1] = 3333   //不是响应式
app.$set(app.arr, 1, 3333)  //是响应式

app.arr.length = 3   //不是响应式
app.arr.splice(3)  //是响应式
  • 声明响应式: property 由于 Vue 不允许动态添加根级响应式 property,所以你必须在初始化实例前声明所有根级响应式 property,哪怕只是一个空值
  • Vue 在更新 DOM 时是异步执行的,为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。
    • Vue.nextTick(callback)或实例方法app.$nextTick(callback)
    • $nextTick()返回一个Promise对象,所以你可以使用新的 ES2017async/await 语法完成
     this.title = ''

     this.$nextTick(() => {
         alert(this.title)
     })

     this.title = 123
	//alert(123)
参考文档

结语

如果对你有帮助的话,请点一个赞吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值