Vue中的数据劫持

  大家好,今天我给大家讲解一下Vue中的数据劫持是如何实现的

  1.在这之前呢,不知道大家知不知道 Object.defineProperty 这个属性呢,如果知道的话,请忽略这一段。

    1. 语法:Object.defineProperty(obj, prop, descriptor) 
    2. 参数:
      1. obj: 要在其上定义属性的对象。
      2. prop: 要定义或修改的属性的名称或名称
      3. descriptor: 定义或修改的属性的描述符。
    3. 返回值:传递给函数的对象。(返回值这个一般不怎么用)

    而在这个 descriptor 有很多的属性,还有 get 和 set 的方法,这里就介绍了 get 和 set 这两个方法,其它的可以去官网了解一下。  

    get: 用作属性的吸气剂或undefined没有吸气剂的函数当访问该属性时,将调用该函数而无需使用参数,并且将其this设置为访问该属性所通过的对象(由于继承,它可能不是在其上定义该属性的对象)。返回值将用作属性的值。
默认为undefined

    set: 用作属性的setter的函数,或者undefined如果没有setter 的函数。将属性分配给该函数时,将使用一个参数(将值分配给该属性)并将this该对象设置为分配该属性的对象来调用此函数。
默认为undefined

       这个就是官网的介绍啦,就我的个人理解

    1. get 就是返回这个属性的值,也就是说,每次获取这个属性的值时,返回的都是我们这里定义的返回值
    2. set 就是当这个属性的值重新赋值的时候要做的事情,可以自己定义,可以是返回新值,也可以是返回你自己定义的值

       

      废话不多说,我们来试验一下。

       let obj = {
                name: '小明',
                age: 21
            }
            function fun(obj,name){
                let value = obj[name]
                Object.defineProperty(obj,'name',{
                    //get 方法就是每次获取这个属性的值时,执行的方法
                    get(){
                        console.log('我是 get 中的')
                        return  '我是 get 获取的' + value
                    },
                    //set 方法就是每次设置这个属性的值时,执行的方法
                    set(newVal){ //newVal是给当前的值从新赋值的值,也就是新值
                        console.log('我是 set 中的')
                        value = ',我是 set 设置的' + newVal
                    }
                })
            }
            fun(obj,'name')
            console.log(obj.name) //打印两次 1、我是 get 中的  2、我是 get 获取的小明
            obj.name = '小红' //打印一次 1、我是 set 中的
            console.log(obj.name) //打印两次 1、我是 get 中的  2、我是 get 获取的,我是 set 设置的小红

       

   2、Vue 中的数据劫持也就使用了这样的方法,让我们看看 Vue 中是如何实现的吧!

  

/**
 * 数据劫持
 */
class Observer{
    constructor(data) {
        this.observer(data);
    }
    observer(data){
        //如果是对象才观察
        if(data && typeof data === 'object'){
            
            for (let key in data) { //循环 data 中的所有子项
                this.defineReactive(data,key,data[key]);
            }
        }
    }
    //实现数据劫持
    defineReactive(obj,key,value){
        this.observer(value); //如果传进来的参数是对象,就回调一下这个函数,就是一个递归函数
        
        let dep = new Dep(); //给每一个属性都添加一个具有发布和订阅的功能
        
        Object.defineProperty(obj,key,{
            get(){
                //创建watcher时,会获取到对应的内容 并且把watcher放到了全局上
                Dep.target && dep.addSub(Dep.target);
                return value;
            },
            set: (newVal)=>{
                if(value !== newVal){
                    this.observer(newVal); //给设置的新值也加上 get set 方法
                    value = newVal;
                    dep.notify(); //执行观察者更新时的函数
                }
                
            }
        })
    }
}

   

  上面就是Vue中实现数据劫持的过程,当然,数据劫持中的 watcher 观察者, Dep 发布和订阅这里就不介绍了,下一篇在为您介绍。

原文地址:https://www.cnblogs.com/nie5135257/p/12110988.html