稍微学一下Vue的数据响应式(Vue2及Vue3区别)

2020-06-12 20:51:33易采站长站整理

// getter 中收集依赖时从全局对象上拿到这个 Watcher 实例
let value = this.getter.call(this.vm, this.vm);
window.target = undefined;
return value;
}
update() {
const oldValue = this.value;
this.value = this.get();
// 将旧值与新值传递给回调函数
this.cb.call(this.vm, this.value, oldValue);
}
}

对于第一点,主动将自己收集到 Dep 实例中,Watcher 中设计的非常巧妙,在 get 中将自身 Watcher 实例挂到全局对象上,然后通过获取数据触发 getter 来实现依赖收集。

第二点实现很简单,只需要将构造函数参数中的回调函数保存并在 update 方法中调用即可。

构造函数中的 parsePath 方法就是从 Vue 实例的 data 上通过表达式获取数据,比如表达式为 “user.name” 则需要解析该字符串然后获取 data.user.name 数据。

总结

数据先通过调用 new Observer() 为每项属性添加变化侦测,并创建一个 Dep 实例用来保存相关依赖。在读取属性值时保存依赖,修改属性值时通知依赖;
Dep 实例的 subs 属性为一个数组,保存依赖是向数组中添加,通知依赖时遍历数组一次调用依赖的 update 方法;
依赖是一个 Watcher 实例,保存了数据变化时需要进行的操作,并将实例自身放到全局的一个位置,然后读取数据触发数据的 getter,getter 中从全局指定的位置获取到该 Watcher 实例并收集在 Dep 实例中。

以上就是 Vue2 中的响应式原理,在 Observer 处理完后,外界只需要通过创建 Watcher 传入需要监听的数据及数据变化时的响应回调函数即可。

Vue3

Vue3 中每个功能单独为一个模块,并可以单独打包使用,本文仅简单讨论 Vue3 中与数据响应式相关的 Reactive 模块,了解其内部原理,与 Vue2 相比又有何不同。

因为该模块可以单独使用,先来看一下这个模块的用法示例:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue3 demo</title>
</head>
<body>
<div id="app">
<div id="count"></div>
<button id="btn">+1</button>
</div>
<script src="./vue3.js"></script>
<script>
const countEl = document.querySelector('#count')
const btnEl = document.querySelector('#btn')
// 定义响应式数据
const state = reactive({
count: 0,
man: {
name: 'pan'
}
})
// 定义计算属性
let double = computed(() => {
return state.count * 2