笔记

ECMA组织,正在尝试将 Object身上有用的东西移植到 Reflect身上。
例如:

let obj = {a:1,b:2}
//为 obj 添加 属性c
Object.defineProperty(obj,'c',{get(){return 3}})
//如果再次添加 属性c,就会导致当前线程因报错停止往下执行。
Object.defineProperty(obj,'c',{get(){return 4}})

如果改用 Refect, 则不会出现因重复定义出错而终止线程继续执行:

let obj = {a:1,b:2}
//为 obj 添加 属性c
const x1 = Refect.defineProperty(obj,'c',{get(){return 3}})
console.log("x1=",x1) //x1=true
//如果再次添加 属性c,虽出错但可继续往下执行。
const x2 = Refect.defineProperty(obj,'c',{get(){return 4}})
console.log("x2=",x2) //x2=false

为了及时发现上面类型x2这种出错,需要借助try{}catch{}:

try {
    Object.defineProperty(obj,'c',{
        get(){
            return 3
        }
    })
    Object.defineProperty(obj,'c',{
        get(){
            return 4
        }
    })
} catch (error) {
    console.log(error)
}  

Reflect的这种 出错不终止执行 是为了 封装函数 相对更加友好一些 ^_^。

源码

模拟Vue3 实现响应式

//#region 
//window.Proxy
const p = new Proxy(person,{ //捕获属性变化
    //有人读取p的某个属性时调用
    //    propName: 属性名
    get(target,propName){
        console.log(`有人读取了p身上的${propName}属性`)

        //return target[propName]
        return Reflect.get(target,propName)
    },

    //有人修改p的某个属性、或给p追加某个属性时调用
    set(target,propName,value){
        console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)

        //target[propName] = value
        Reflect.set(target,propName,value)
    },

    //有人删除p的某个属性时调用
    deleteProperty(target,propName){
        console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)

        //return delete target[propName] //如果真删掉,返回true 否则,返回false
        return Reflect.deleteProperty(target,propName)
    }
})

调试:
Chrome浏览器 F12 控制台:

person
p.name='李四'
person

总结

Vue3.0中的响应式原理

vue2.x的响应式

  • 实现原理:

    • 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)。

    • 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。

      Object.defineProperty(data, 'count', {
          get () {}, 
          set () {}
      })
  • 存在问题:

    • 新增属性、删除属性, 界面不会更新。
    • 直接通过下标修改数组, 界面不会自动更新。

Vue3.0的响应式