上篇主要对数组格式数据进行响应式处理,vue 有set 和del 方法可以对数组和对象进行修改和删除。代码如下:
数组类型的数据修改和删除时候,只需要调用splice方法就可以,在上一篇数组响应是在get方法中属性为数组格式时进行依赖的注入,现在在每个属性都注入,这样调用set方法时候,才能在_ob_属性中去触发依赖函数的更新。
import Dep from "./dep"; import { hasProto, def,hasOwn } from "./utils/index"; import { arrayMethods } from "./array"; const arrayKeys = Object.getOwnPropertyNames(arrayMethods); const NO_INIITIAL_VALUE = {}; function defineReactive(obj, key, val, shallow) { console.log(obj,key,val,'kkkkkddd') // 获取当前属性有没有自定义方法; 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) } /******新增 *************************/ //给每个属性都添加一个依赖函数,这样对象通过set新增一个属性后就可以去触发更新 childOb.dep.depend(); } /************************************/ } //如果有自定义方法则调用 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); // 递归进行 } } } // set 方法 export function set(target,key,val){ // 如果是数组类型 if(Array.isArray(target)){ target.length = Math.max(target.length,key) target.splice(key,1,val) return val } //如果是对象类型 修改target自身的属性 if(target[key] && !(key in Object.prototype)){ Object.prototype = val; return val } let ob = target.__ob__; // 前面数据响应式每个属性都添加了_ob_属性,如果没有说明target不是响应式的数据 if(!ob){ target[key] = val; return val } // 如果是响应式数据,则将新增的值变为响应式 defineReactive(target, key, val,false); // 让依赖的方法更新 ob.dep.notify() } //delete 方法 export function del(target,key){ // 如果是数组类型 if(Array.isArray(target)){ target.length = Math.max(target.length,key) target.splice(key,1) return } //如果target是对象类型 const ob = target.__ob__; if (!hasOwn(target, key)) { return; } delete target[key]; if (!ob) { return; } ob.dep.notify(); }
import { observe,set,del } from "./reactive"; import { Watcher } from "./watcher"; const data = { test2: { dd: "aa", }, arr: ["a",{test:'oo'},['a']], }; const recursion = () => { console.log(data.test2.hh); }; const updateArr = () => { data.arr.map((item) => console.log(item)); }; observe(data); // 深度响应 new Watcher(recursion); // 数组方法响应 new Watcher(updateArr); //数组set 方法 //set(data.arr,4,'add') // 对象set 方法 //set(data.test2,'hh','ppp') //数组删除 //del(data.arr,0) //对象删除方法 del(data.test2,'dd')
标签:set,数组,val,vue,del,key,let,data From: https://www.cnblogs.com/hardmeng/p/17169305.html