手写vue2.0源码三之data对象响应式

文章类型:Vue

发布者:hp

发布时间:2023-05-25

前面已经实现了通过vm.xxx来获取数据,但是数据不是响应式的,这节,将对对象进行响应式处理,就需要用到观察者模式

一:初始化的时候,定义一个方法来观察,观察数据

  /*
   我们就需要观察这些对象
   */
   observe(data)

二:把数据进行判断是否存在,存在则交给一个专门的函数,观察者去处理

/* 
观察数据
*/
import Observer from "./observer"
export default function observe(data){
    if(typeof data!=='object' || data===null) return

    /*否则就需要把数据交给观察者 */
    
    return new Observer(data)
}

三:观察者拿到具体的数据,那么就需要进行区分,是对象还是数组,走不同的方法去处理

export default function Observer(data){
    /*
    针对对象和数组方式
    采取不一样的方式
    说白了就是不同的处理方式
    */
   if(Array.isArray(data)){
    //数组
   }else{
    //对象
    this.walk(data)
   }
}

四:针对对象,挂载一个原型方法去处理,循环找到每个属性,然后交给另外一个函数去专门处理对象

//增加一个原型方法
Observer.prototype.walk=function(data){
/* 
这里就需要对对象的所有属性进行重新定义
绑定get,set方法

*/

 var keys=Object.keys(data)
 console.log(keys)
 
 for (let index = 0; index < keys.length; index++) {
    var key=keys[index],
    value=data[key]
    defineReactiveData(data,key,value)
 }
}

五:专门处理对象响应式的函数,进行添加get,set,对象里面也阔能是对象,那么就需要重新走之前的逻辑,也就是观察->观察者->数据处理,说白了就是递归进行

export default function defineReactiveData(data,key,value){
    /*value 
    有阔能还是数组或者对象
    那么就还需要进行递归遍历
    */

    observe(value)
    Object.defineProperty(data,key,{
        get(){
            console.log("响应式读取",value)
            return value
        },
          set(newValue){
            /*修改的时候,如果相等,那么就没必要修改 否则修改 */
            if(newValue===value) return
            /*有可能还是对象数组,那么又重新观察->观察者->数据属性添加 */
            observe(value)
            value=newValue

        }
    })
}

六:这样就实现响应式了,每个对象属性都添加了get,set,通过读取能触发到

let vm=new Vue({
    el:'#app',
    data(){
        return{
            msg:456,
            info:{
                name:'张三',
                age:18
            }
        }
    }
})
console.log('vm')
console.log(vm)
console.log(vm.info.name)