vue 模拟set del 方法
上篇主要对数组格式数据进行响应式处理,vue 有set 和del 方法可以对数组和对象进行修改和删除。代码如下:
数组类型的数据修改和删除时候,只需要调用splice方法就可以,在上一篇数组响应是在get方法中属性为数组格式时进行依赖的注入,现在在每个属性都注入,这样调用set方法时候,才能在_ob_属性中去触发依赖函数的更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | 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(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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' ) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具