• 解密vue数据更新


    1.Object.defineProperty(obj,key,desc);

      用法:1.给对象新增属性和特性

         2.修改对象属性值和特性

          desc(属性特性):

            1.enumerable:boolean 可枚举

            2.writable :boolean 可写

            3.value:any 赋值

            4.get 取值

            5.set 改值

    2.思路:

      对象的赋值和改值其实是通过Object.defineProperty的get和set特性来实现的,一般默认模式。

      通过改写属性的get和set的特性,来实现对一个对象的监听。

    3.举例:

      

    var obj = {age:23};
    console.log(obj.age);    //23
    
    Object.defineProperty(obj,'age',{
        get(){
            return 24;
        }    
    });
    console.log(obj.age);  //24
    
    obj.age = 25;
    console.log(obj.age);  //24
    

      原理:对象属性和赋值取值都会触发自身的get和set特性。

    4.实现:

     /*js 监听器*/
        var transi = "";
        function observe(obj,key){
          if(obj[key] && (typeof obj[key] == 'object')){
            Object.keys(obj[key]).forEach((v,index)=>{
              observe(obj[key],v,obj[key][v]);
            });
          } else {
            Object.defineProperty(obj,key,{
              set(newV){
                transi = newV;
                console.log('值改变');
              },
              get(){
                console.log('新值为' + transi);
                return transi;
              }
            })
          }
        }
        var obj = {name : 'wang',age:{max:12,good:{at:30}}};
        observe(window,'obj');
        obj.age.good.at = 44;
        console.log(obj.age.good.at);
    

     5.延伸:

      vue的双向绑定机制:当改变一个值时,在这个值的set特性中触发其他值的改变,实现数据实时更新的机制。

     6.核心:

      1.observer观察者: 观察一个对象,当某一属性改变时,触发set特性,由set触发与之关联的属性,哪些与之关联,怎么建立起关系?需要一个订阅者,即为一个数组,存放一些关联的对象。

      2.watcher订阅者: 订阅者需要自己的更新机制,在set中被触发时需要及时更新自己的数据,再渲染到页面上,需要complier来解析页面,实现view层改变。

      3.complier解析: 通过js获取指令模板,正则匹配换值,将操作封装放进set函数中实现view层自动更新。

     7.数组的push、shift、concat、unshift、pop等api触发数据更新重新渲染:

      数组没法像对象可以对字段的监听,若想实现监听,必然需要重写push、shift、concat、unshift、pop这些函数

      方案一:

    const push1 = Array.prototype.push;
          Array.prototype.push = function () {
              render(); //拦截进行数组render重新渲染
             return push1.apply(this,arguments);
          };

      此方案虽然实现数组的监听,但也改变了所有数组的原型,而且不是所有数组都需要监听;

      方案二:

      

    中心思想:代理原型
    var obj = Object.create(Array.prototype);
    var prototypePush = Array.prototype.push;
    obj.push=function () {
     render(); //拦截进行数组render重新渲染
        return prototypePush.apply(this,arguments);
    };
    var arr = [];
    arr.__proto__ = obj;
  • 相关阅读:
    第5章 简单的C程序设计——循环结构程序设计
    第4章 简单的C程序设计——选择结构程序设计
    通过wget工具下载指定文件中的URLs对应的资源并保存到指定的本地目录中去并进行文件完整性与可靠性校验
    Kaflka介绍
    分布式与集群
    Golang菜鸟教程day01
    优秀的github项目
    Golang教程
    windows下安装GDB
    nginx部署
  • 原文地址:https://www.cnblogs.com/changyaoself/p/9272343.html
Copyright © 2020-2023  润新知