然后 我们来学一下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
运行结果如下
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中将记录的值返回回去
但其实 我们现在这个写法 真的是非常的捞 看着
这个 时候 我们就可以定义一个函数 用闭包来写
我们在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
然后 我们尝试修改响应式变量 看看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
运行结果如下
很显然 事件都有被监听
其实defineReactive就是提供了一个闭包的环境