首页 > 其他分享 >vue2 模拟响应式数组优化2

vue2 模拟响应式数组优化2

时间:2023-02-28 18:11:07浏览次数:48  
标签:key const vue2 val let 数组 data 模拟

上一篇主要是对数组类型进行响应式处理,这次主要对数组里面的属性值、嵌套数组、数组新增后的值进行响应式处理。

如下文:执行下面方法,数组的依赖函数不会触发

import { observe } from "./reactive";
import { Watcher } from "./watcher";

const data = {
  arr: ["a",{test:'oo'},['a']],
};

const updateArr = () => {
  data.arr.map((item) => console.log(item));
};

observe(data);

new Watcher(updateArr);

// 数组里面值进行响应式
//data.arr[1].test = 'lll'
//嵌套数组响应
//data.arr[2].push('lll')
//数组新增值后响应
data.arr.push(['ppp']);
data.arr[3].push('uuu')

 新增代码如下:

import Dep from "./dep";
import { hasProto, def } from "./utils/index";
import { arrayMethods } from "./array";
const arrayKeys = Object.getOwnPropertyNames(arrayMethods);
const NO_INIITIAL_VALUE = {};
function defineReactive(obj, key, val, shallow) {
  // 获取当前属性有没有自定义方法;
  let property = Object.getOwnPropertyDescriptor(obj, key);
  // 判断当前属性有没有自定义get set 方法
  let getter = property && property.get;
  let setter = property && property.set;
  // 没有val值,去obj里面的
  if (
    (!getter || setter) &&
    (val = NO_INIITIAL_VALUE || arguments.length == 2)
  ) {
    val = obj[key];
  }

  const dep = new Dep(); // 持有一个 Dep 对象,用来保存所有依赖于该变量的 Watcher

  // 如果有深度对象,则深度监听
  let childOb = !shallow && observe(val, false);

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function () {
      //添加依赖函数
      if (Dep.target) {
        // dep.addSub(Dep.target);
        dep.depend();

        /******新增 *************************/
        if (childOb) {
          if (Array.isArray(val)) {
            // 如果当前值是数组,给数组生成的observer.dev添加依赖函数
            childOb.dep.depend();
			//循环数组,对嵌套数组进行依赖收集
			dependArray(val)
          }
        }
        /************************************/
      }
      //如果有自定义方法则调用
      let value = getter ? getter.call(obj) : val;
      return value;
    },
    set: function (newVal) {
      if (setter) {
        setter.call(obj, newVal);
      } else {
        val = newVal;
      }
      // 如果对一个对象整体赋值后,再修改对象属性也没有响应效果,在set也监听下

      childOb = !shallow && observe(newVal, false);
      //执行依赖当前属性的依赖函数
      dep.notify();
    },
  });
}

export class Observer {
  // shallow 属性判断是否需要深度监听
  constructor(data, shallow = false) {
    this.dep = new Dep(); // 新增dep
    def(data, "__ob__", this); // 每个数据都新增_ob_属性绑定当前Observer实例
    if (Array.isArray(data)) {
      // 判断当前值是否是数组类型,是否有__proto__属性,将重写的方法指向原型
      if (hasProto) {
        data.__proto__ = arrayMethods;
      } else {
        for (let i = 0, l = arrayKeys.length; i < l; i++) {
          const key = arrayKeys[i];
          def(data, key, arrayMethods[key]);
        }
      }
//添加对数组里面每一个值进行响应式监听 this.observeArray(data) } else { this.walk(data, shallow); } } walk(data, shallow) { let keys = Object.keys(data); for (let key of keys) { defineReactive(data, key, NO_INIITIAL_VALUE, shallow); } } //新增 循环数组,对数组里面值进行监听 observeArray(data){ for(let i=0;i<data.length;i++){ observe(data[i]) } } } export function observe(data, shallow = false) { if (data !== null && typeof data === "object") { return new Observer(...arguments); } else { return false; } } //多层数组嵌套响应 function dependArray(value) { for (let e, i = 0, l = value.length; i < l; i++) { e = value[i]; if (Array.isArray(e)) { e && e.__ob__ && e.__ob__.dep.depend(); dependArray(e); // 递归进行 } } }

  

/*
 * not type checking this file because flow doesn't play well with
 * dynamically accessing methods on Array prototype
 */

import { def } from "./util";

const arrayProto = Array.prototype;
export const arrayMethods = Object.create(arrayProto);

const methodsToPatch = [
    "push",
    "pop",
    "shift",
    "unshift",
    "splice",
    "sort",
    "reverse",
];

/**
 * Intercept mutating methods and emit events
 */
methodsToPatch.forEach(function (method) {
    // cache original method
    const original = arrayProto[method];
    def(arrayMethods, method, function mutator(...args) {
        const result = original.apply(this, args);
        const ob = this.__ob__;
        /******新增 *************************/
        let inserted; 
        switch (method) {
            case "push":
            case "unshift":
                inserted = args;
                break;
            case "splice":
                inserted = args.slice(2);
                break;
        }
        if (inserted) ob.observeArray(inserted);
        /************************************/
        // notify change
        ob.dep.notify();
        return result;
    });
});

  

标签:key,const,vue2,val,let,数组,data,模拟
From: https://www.cnblogs.com/hardmeng/p/17165490.html

相关文章

  • #yyds干货盘点# LeetCode面试题:搜索旋转排序数组
    1.简述:整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0<=k<nums.length)上进行了旋转,使数组变为[nums[k],nums[k+1],......
  • #yyds干货盘点# LeetCode面试题:在排序数组中查找元素的第一个和最后一个位置
    1.简述:给你一个按照非递减顺序排列的整数数组nums,和一个目标值target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值target,返回 [-1,-1]......
  • 2357. 使数组中所有元素都等于零 (Easy)
    问题描述2357.使数组中所有元素都等于零(Easy)给你一个非负整数数组nums。在一步操作中,你必须:选出一个正整数x,x需要小于或等于nums中最小的非零元素。n......
  • 2023.2.23模拟赛
    T1题意:给一个由"("和")"组成的字符串s,\(ans_{i}\)表示\(i\)所在合法字符串的个数,求\(\sum_{i=1}^{n}(ans_{i}\timesi\mod(10^{9}+7))\)思路:\(f_{i}\)表示\(i\)所对......
  • 2341. 数组能形成多少数对 (Easy)
    问题描述2341.数组能形成多少数对(Easy)给你一个下标从0开始的整数数组nums。在一步操作中,你可以执行以下步骤:从nums选出两个相等的整数从nums中移除这......
  • JavaScript Array(数组) 对象
    JavaScript Array(数组) 对象数组对象的作用是:使用单独的变量名来存储一系列的值。在线实例创建数组,为其赋值:实例varmycars=newArray();mycars[0]="Saab......
  • VUE2 自定义指令
    简写方式(有弊端)<h2>{{name}}</h2><h2>当前的n值是:{{n}}</h2><h2v-big="n">放大10倍后的n值是:{{n}}</h2><button@click="n++"></button>data(){return{......
  • Java数组
    Java数组什么是数组数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据成为一个数组元素,每个数组元素可......
  • 力扣---33. 搜索旋转排序数组
    整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0<=k<nums.length)上进行了旋转,使数组变为[nums[k],nums[k+1],...,......
  • 数组
                         ......