本文已参与「新人创作礼」活动,一起开启掘金创作之路。
深入浅出之vue(原生实现变化监听)
Object的变化侦测
常见的侦测变量变化的方法有Object.defineProperty和ES6的Proxy
Object.defineProperty
Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
Object.defineProperty(obj, prop, desc)
- obj 需要定义属性的当前对象
- prop 当前需要定义的属性名
- desc 属性描述符
一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性
属性描述符(desc)
通过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符(value,writable),存取描述符(getter,setter函数)
数据描述符
let Person = {}
Object.defineProperty(Person, 'name', {
value: 'jack',
writable: true // 是否可以改变
})
存取描述符
let Person = {}
let temp = null
Object.defineProperty(Person, 'name', {
get: function () {
return temp
},
set: function (val) {
temp = val
}
})
- configrable 描述属性是否配置,以及可否删除
- enumerable 描述属性是否会出现在for in 或者 Object.keys()的遍历中
configrable
- configurable: false 时,不能删除当前属性,且不能重新配置当前属性的描述符(有一个小小的意外:可以把writable的状态由true改为false,但是无法由false改为true),但是在writable: true的情况下,可以改变value的值
- configurable: true时,可以删除当前属性,可以配置当前属性所有描述符。
enumerable
ES6的Proxy
待定
通过Object.defineProperty实现vue监听变量
<template>
<h1>{{name}}</h1>
</template>
模板中使用了name,当其发送变化则需要通知所有使用他的地方. 所以最直接明了的方法就是先收集所有使用了name的依赖,当其属性发生了变化就遍历通知.总结起来,其实就一句话,在getter中收集依赖,在setter中触发依赖。