vue2响应式原理

一、初识响应式原理

如果我们在 Vue 实例中声明过的数据发生了改变,那么所有用到这份数据的视图都会更新重新渲染,我们称这些数据就是响应式数据。响应式概括来说就是 数据驱动视图的自动更新

<div id="app">
  {{ obj.message }}
</div>
let data = {
  obj: {
    message: 'Hello Vue!',
  },
}

new Vue({
  el: '#app',
  data,
})

setTimeout(() => {
  data.obj = {
    message: 'Obj have changed!',
  }
}, 1000)
setTimeout(() => {
  data.obj.message = 'Message have changed!'
}, 2000)

分析:

初次渲染时 Vue 会将 “ Hello Vue! ” 渲染在页面中,在一秒后修改了 data.obj 发生变化,页面也随之更新为 “ Obj have changed! ”,随后又过一秒 data.obj.message 被修改,页面显示为 “ Message have changed! ”

二、响应式原理的实现

为了实现响应式,vue必须要做以下两件事:

(1)数据什么时候变化了 --- 监视数据/数据劫持
(2)哪些地方用到了数据 --- 解析模板

 

1、监视数据

Vue 使用了 3 个类,实现了数据的拦截、更新订阅与发布:

Observer(监视者类):监视数据的变化,在数据变化时告诉通知者,在这个类中将数据的所有属性用 Object.defineProperty 重新定义一遍,绑定了存取器(getter/setter)。

Dep(通知者类):通知订阅者更新视图,因为一个数据可能被多处使用,所以一个通知者会存储多位订阅者。

Watcher(订阅者类):用于存储数据变化后要执行的更新函数,调用更新函数可以使用新的数据更新视图。

Vue 在初始化数据时,会使用 Object.defineProperty 重新定义 data 中的所有属性,为对象中的每一个属性,设置 get 和 set 方法,进行数据劫持/监听;get 值是一个函数,当属性被访问时,会触发 get 函数,set 值同样是一个函数,当属性被赋值时,会触发 set 函数;

var obj={    
    name:Vue是响应式吗?
}

Object.defineProperty(obj,"name",{
    get(){        
        console.log("get方法被触发")
    },
    set(val){        
        console.log("set方法被触发")
    }
})

var str = obj.name  //get方法被触发
obj.name = "Vue是响应式的"  // set方法被触发

2、解析模板

数据监视完毕后,Vue 会解析模板,模板解析的内容较为复杂,这一过程会创建虚拟节点 vnode,匹配到 {{ }} v- 等响应式写法,会根据当前节点的类型、响应式语法等建立该节点的更新函数 patch ,将数据与视图绑定。

Vue通过依赖收集去更新视图:data 中每个声明的属性都会有一个专属的依赖收集器dep.subs数组,当页面使用到 某个属性时,触发 ObjectdefineProperty - get函数,页面的 watcher 就会被放到属性的依赖收集器 subs 中进行保存。它知道谁依赖它之后,它就可以在发生改变的时候,通知 依赖它的页面,从而让页面完成更新;watcher可用于 进行视图更新。

 

posted @ 2023-06-01 21:28  CodeFan*  阅读(178)  评论(0编辑  收藏  举报