vue2和vue3响应式原理简版

65 阅读1分钟

vue2响应式原理概述

  • vue2的响应式原理主要通过Object.defineProperty(),实现对属性的读取、修改进行拦截。
  • Object.defineProperty()有可传入三个参数
    • 对象
    • 对象的属性名
    • 属性描述符
      • 其中属性描述符又可作划分
        • 数据描述符:
          • value:属性的值,默认为undefined
          • writable:是否可以修改属性的值,默认为false
        • 存取描述符
          • get:当属性被访问时调用
          • set:当属性被修改时调用
        • 其他描述符
          • configurable:是否可以删除当前属性,默认为false
          • enumerable:属性是否可枚举,不可枚举则某些情况该属性不会被遍历出来,默认为false

vue2响应式简写

     let mvp_coder = {
            name:'jack',
            age:99
        }

        let sim_coder = {}

        // 模拟vue2实现响应式
        Object.defineProperty(sim_coder,'name',{
            configurable:true,
            get(){
                return mvp_coder.name
            },
            set(value){
                console.log('监听到有人修改name,需要去更新页面');
                mvp_coder.name = value
            }
        })
        Object.defineProperty(sim_coder,'age',{
            get(){
                return mvp_coder.age
            },
            set(value){
                console.log('监听到有人修改age,需要去更新页面');
                mvp_coder.age = value
            }
        })

image.png

vue2存在的问题
  • 新增属性、删除属性, 界面不会更新。

image.png

image.png 可以使用this.$set(array, index, data)解决

Vue3响应式原理概述

    1. 通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。
 const dif_coder = new Proxy(mvp_coder,{
            get(target, propName){
                console.log(`读取了dif_coder身上的${propName}`,target[propName]);
                return target[propName]
            },
            set(target, propName, value){
                console.log(`修改了dif_coder身上的${propName}`);
                target[propName] =  value
            },
            defineProperty(target, propName){
                console.log(`删除了dif_coder身上的${propName}`);
                return delete target[propName]
            }
      })

image.png

    1. 通过Reflect(反射): 对源对象的属性进行操作。
    • Reflect是什么? es6的新方法,会返回boolean值

image.png

vue3响应式简写

 const dif_coder = new Proxy(mvp_coder,{
            get(target, propName){
                console.log(`读取了dif_coder身上的${propName}`,target[propName]);
                return Reflect.get(target, propName)
            },
            set(target, propName, value){
                console.log(`修改了dif_coder身上的${propName}`);
                return Reflect.set(target, propName, value)
            },
            defineProperty(target, propName){
                console.log(`删除了dif_coder身上的${propName}`);
                return Reflect.deleteProperty(target, propName)
            }
})