vue2源码-三、数组的劫持

数组的劫持

  1. 数组劫持的思路

    对于数组劫持的目标是实现数组的响应式:

    • Vue中,我们很少会使用索引进行操作数组,并且认为有七个方法能够改变数组:

      pushpopspliceunshiftreversesort。所以,需要对七个方法进行特殊处理,是他们能够劫持到数组的数据变化,就能够实现数组的响应式。

      因此,要单独处理,在Observer初始化时会walk遍历属性实现递归;所以就需要将数组响应式的处理逻辑单独出来,重写这个七个方法:

      import { arrayMethods } from "./array";
      
      class Observer {
        constructor(value) {
          if(isArray(value)){
            // 对数组类型进行单独处理:重写 7 个变异方法
          }else{
            this.walk(value);
          }
        }
      }
      
  2. 数组的重写的注意

    数组重写不能影响非响应式数组。

    所以,对响应式数据中数组的这七个方法进行拦截:优先从链上查找到并使用重写方法啊,其他方法依然走原生逻辑。

    // 希望重写数组中的部分方法
    let oldArrayProto = Array.prototype;
    
    // newArrayProto.__proto__ = oldArrayProto
    export let newArrayProto = Object.create(oldArrayProto);
    
    // 找到所有的变异方法
    let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"];
    
    methods.forEach((method) => {
      // arr.push(1,2,3)
      newArrayProto[method] = function (...args) {
        // 重写了方法
        // push.call(arr)
        const result = oldArrayProto[method].call(this, ...args); // 内部调用原来的方法,函数的劫持,切片编程
    
        // 新增的数据进行劫持
        let inserted;
         // 后面的
        let ob = this.__ob__;
        switch (method) {
          case "push":
            inserted = args;
            break;
          case "unshift":
            inserted = args;
            break;
          case "splice":
            inserted = args.slice(2);
            break;
          default:
            break;
        }
        if (inserted) {
          // 对新增的内容进行观测
          ob.observeArray(inserted);
        }
    	// 后面的
        ob.dep.notify();
        return result;
      };
    });
    
    
    • 首先,拿到数组的所有原生方法oldArrayProto,通过Object.create原型继承放到arrayMethods原型链上,相当于将原生方法向后移动了一层。
    • value为数组类型时,修改数组的原型链为arrayMethods;此时,原本在value.__propto__上原生方法。
    • arrayMrthods进行处理,在第一层对7个变异方法进行重写,利用js原型链查找机制,就实现了对原生方法的拦截。
posted @   楸枰~  阅读(88)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示