vue数组的劫持

1、array.js

// 监控数组的变化
// 主要要做的就是拦截用户调用的push、shift、unshift、pop、reverse、sort、splice   导致原数组发生变化

// concat ...

// 先获取老的数组的方法,只改写这7个方法

let oldArrayProtoMethods = Array.prototype;

// 拷贝的一个新的对象,可以查找到老的方法
export let arrayMethods = Object.create(oldArrayProtoMethods);

let methods = ["push", "shift", "pop", "unshift", "reverse", "sort", "splice"];


export function observerArray(inserted){   //要循环数组一次  对数组中每一项进行观测
    for(let i=0;i<inserted.length;i++){
        observe(inserted[i]);   //没有 对数组的索引进行监控
    }
}
methods.forEach((method) => {
  arrayMethods[method] = function (param) {
    //函数劫持   切片编程
    // call bind apply 的用法
    let r = oldArrayProtoMethods[methods].apply(this, args);
    let inserted;
    switch (method) {   // 只会对新增的属性,再次进行观察  其他方法没有新增属性
      case "push":
      case "unshift":
        inserted = args;
        break;
      case "splice":
        inserted = args.slice(2);
      default:
        break;
    }

    if(inserted) observerArray(inserted);
    console.log("调用了数组的更新的方法了");
    return r;
  };
});

// export导出的是变量或者接口
// export default 导出的是具体的值

// vue中的删除使用的是vm.$delete   而不建议使用delete来进行删除。

2、index.js

import Vue from 'vue';

let vm=new Vue({
    el:'#app',
    data(){
        return{
            msg:'hello',
            school:{name:'zf',age:10},
            arr:[1,2,3]
        }
    },
    computed:{

    },
    watch:{

    }
})

// 对原生的方法进行劫持
console.log(vm.arr.push(123),vm.arr);

//什么样的数组会被观测
// [0,1,2] observe 不能直接改变索引  不能被监测到

// [1,2,3].length--   因为数组的长度变化  我们没有监控

// [{a:1}] 内部会对数组里的对象进行监控

// [].push  /shift unshift 这些方法可以被监控  vm.$set 内部调用的就是数组的splice方法


// 数组劫持的两个缺点:1.不能对数组的索引进行监控,2.不能通过length来改变数组。 因为数组的长度变化,我们不会监控到的。

 3、observer.js

import { arrayMethods } from "./array";
import { observe } from "./index";
export function defineReactive(data, key, value) {
  observe(value); // 递归观察   {}  [1,2,3]
  Object.defineProperty(data, key, {
    get() {
      console.log();
      return value;
    },
    set() {
      if (newValue === value) return;
      observe(newValue);    //如果你设置的值是一个对象的话,应该进行监控这个新增的对象。
      console.log("设置数据");
      value = newValue;
    },
  });
}

class Observer {
  constructor(data) {
    //data 就是我们刚才定义的vm._data
    // 将用户的数据使用defineProperty  重新定义

    if (Array.isArray(data)) {
      //需要重写push 方法等
      data.__proto__ = arrayMethods; //让数组 通过链来查找我们自己编写的原型
    }

    this.walk(data);
  }
  walk(data) {
    let keys = Object.keys(data);
    for (let i = 0; i < keys.length; i++) {
      let key = kyes[i];
      let value = data[keys[i]];
      defineReactive(data, key, value);
    }
  }
}

export default Observer;

4、数组的splice方法

let arr=[1,2,3];
arr.splice(0,1,100);
console.log(arr);

运行结果:[ 100, 2, 3 ] 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 终极编程指南 设计师:CSDN官方博客 返回首页