zoukankan      html  css  js  c++  java
  • Vue响应式原理

      /*
    1.Vue是如何实现实时监听数据变化的?
    通过原生JS的 defineProperty 方法
    
    2.defineProperty方法的特点
    可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象
    
    3.defineProperty用法
    obj: 需要操作的对象
    prop:  需要操作的属性
    descriptor: 属性描述符
    
    Object.defineProperty(obj, prop, descriptor)
    
      */
    
    
      let obj = {};
      // 需求: 给obj对象动态新增一个name属性,并且name属性的取值必须是abc
      Object.defineProperty(obj, 'name', {
        value: 'abc',
        writable: true,  // true 新增的属性值可修改。默认不可修改
        configurable: true, // name属性是否可删除。默认不可删除
        enumerable: true, // 新增的name属性是否可迭代遍历。默认不可
      })
    
      console.log(obj)  // {name: "abc"}
    
    // 默认不可删除新增的属性
    delete obj.name
    /*
    3.1 defineProperty除了可以动态修改/新增对象的属性以外
    还可以在修改/新增的时候给该属性添加get/set方法
    
    3.2 get/set方法特点
    只要通过defineProperty给某个属性添加了 get/set方法
    那么以后只要获取这个属性的值就会自动调用get,设置了这个属性的值就会自动条用set
    
    3.3注意点
    如果设置了get/set方法,那么就不能通过value直接赋值,也不能设置writable: true
    */
    
    let oldValue = "测试数据";
    Object.defineProperty(obj, 'test', {
      configurable: true,
      enumerable: true,
      get() {
        return oldValue
      },
      set(newValue) {
        if(oldValue !== newValue) {
          oldValue = newValue;
        }
      }
    })
    
    
    // 需求:快速监听对象中所有属性的变化
    let obj = {
      name: 'ceshi',
      age: 18
    }
    
    // 只要将需要监听的那个对象传递给Observer这个类
    // 这个类就可以快速的给传入的对象的所有属性都添加get/set方法
    
    class Observer {
      constructor(data) {
        this.observer(data);  // constructor 方法是类的默认方法,创建类的实例化对象时被调用。
      }
    
      observer(obj) {
        if(obj && typeof obj === 'object') {
          // 遍历取出传入对象的所有属性, 给遍历到的属性都增加get/set方法
          for(let key in obj) {
            this.defineRecative(obj, key, obj[key])
          }
        }
      }
    
      // obj: 需要操作的对象
      // attr: 需要新增get/set方法的属性
      // value: 需要新增get/set方法属性的取值
      defineRecative(obj, attr, value) {
        // 如果属性的取值又是一个对象, 那么也需要给这个对象的所有属性添加get/set方法
        this.observer(value);
    
        Object.defineProperty(obj, attr, {
          get(){
            return value;
          },
          set:(newValue)=>{
            if(value !== newValue){
              // 如果给属性赋值的新值又是一个对象, 那么也需要给这个对象的所有属性添加get/set方法
              this.observer(newValue);
              value = newValue;
              console.log('监听到数据的变化, 需要去更新UI');
            }
          }
        })
      }
    }
    
    new Observer(obj);
    // obj.name = '123';
    // obj.age = 23;
    // obj.name.a = 'dtdgf';
    obj.name = {a: 'abc'};
    obj.name.a = '测试文本';
  • 相关阅读:
    移动Oracle数据库表空间文件。
    Web页面嵌入复杂WinForm控件权限问题
    关于bleand2000下面oracle服务器优化
    祝大家新年快乐!
    CentOS安装配置MongoDB及PHP MongoDB 扩展安装配置 新风宇宙
    FastDFS介绍和配置过程 新风宇宙
    ubuntu下安装redisserver和phpredis 新风宇宙
    PHP安装fastDFS扩展 新风宇宙
    用socket发送流数据示用 php://input? 接受post数据(可实现php和c/c++数据通讯) 新风宇宙
    linux操作系统下c语言编程入门 新风宇宙
  • 原文地址:https://www.cnblogs.com/yhquan/p/14551262.html
Copyright © 2011-2022 走看看