> 文章列表 > vue2数据响应式原理(3) 带你手写一个defineReactive响应式函数并理解其本质

vue2数据响应式原理(3) 带你手写一个defineReactive响应式函数并理解其本质

vue2数据响应式原理(3) 带你手写一个defineReactive响应式函数并理解其本质

然后 我们来学一下defineReactive函数
defineReactive其实是一个要声明的函数 基本都是作为一个响应式函数 因为vue的使用比较经典 因此 也成了 响应式的一个代表函数
而定义它的意义在于 defineProperty不好用

具体不好用在哪呢? 我们打开上文用到的项目
将output.js代码修改如下

const output = () => {var obj = {a: 11};Object.defineProperty(obj,'a',{get() {return 31},set(value) {console.log("您正在改变 obj的a属性,修改后的值为",value);}});obj.a = 12;console.log(obj.a);document.getElementById("text").innerHTML = obj.a;
}export default output

运行结果如下
vue2数据响应式原理(3) 带你手写一个defineReactive响应式函数并理解其本质
defineProperty的特性
get会的返回值 为元素最终值 这里 我们赋值时 它先被赋值成了12 然后 当你输出的一瞬间 你获取他的值 触发到了 get 于是 这个get就又把它变回返回的这个 31了

但这个问题也并非误解 我们将output.js代码更改如下

const output = () => {var obj = {a: 11};let temp;Object.defineProperty(obj,'a',{get() {return temp},set(value) {temp = value;console.log("您正在改变 obj的a属性,修改后的值为",value);}});obj.a = 12;console.log(obj.a);document.getElementById("text").innerHTML = obj.a;
}export default output

我们在他们中间 做了一个周转变量 在set中拿到值 然后 在get中将记录的值返回回去
vue2数据响应式原理(3) 带你手写一个defineReactive响应式函数并理解其本质
但其实 我们现在这个写法 真的是非常的捞 看着

这个 时候 我们就可以定义一个函数 用闭包来写

我们在src下创建一个类 叫 dataResp.js
参考代码如下

export const defineReactive = function(data,key,val,enumerable,configurable) {Object.defineProperty(data,key,{enumerable,configurable,get() {return val},set(value) {if(value == val) {return}val = value;}});
}

这样 我们就定义了一个功能的数据响应式声明方法
然后回去将output.js代码更改如下

import { defineReactive } from "./dataResp"
const output = () => {var obj = {};defineReactive(obj,"a",10,true,true);document.getElementById("text").innerHTML = obj.a;
}export default output

这里 我们调用了刚刚写在dataResp.js中的defineReactive函数 第一个参数是要给那个对象声明响应式 我们传入了obj 要给那个键 我们输入了a 然后 他的初始值 我们输入了一个10 后面的enumerable和configurable 就给true
运行结果如下
可以看到 obj.a的值确实是10
vue2数据响应式原理(3) 带你手写一个defineReactive响应式函数并理解其本质
然后 我们尝试修改响应式变量 看看set 和get 会不会触发
dataResp.js代码修改如下

export const defineReactive = function(data,key,val,enumerable,configurable) {Object.defineProperty(data,key,{enumerable,configurable,get() {console.log(`您正在获取${key}的值`);return val},set(value) {console.log(`您正在修改${key}的值`);if(value == val) {return}val = value;}});
}

我们在get和set中设定了输出语句 然后 更改output.js代码如下

import { defineReactive } from "./dataResp"
const output = () => {var obj = {};defineReactive(obj,"a",10,true,true);obj.a = 20;document.getElementById("text").innerHTML = obj.a;
}export default output

这里 我们通过defineReactive声明了obj.a的响应式之后 修改了obj.a
运行结果如下
vue2数据响应式原理(3) 带你手写一个defineReactive响应式函数并理解其本质
vue2数据响应式原理(3) 带你手写一个defineReactive响应式函数并理解其本质

很显然 事件都有被监听

其实defineReactive就是提供了一个闭包的环境

牛粪字体