vue2 模拟响应式数组优化2
上一篇主要是对数组类型进行响应式处理,这次主要对数组里面的属性值、嵌套数组、数组新增后的值进行响应式处理。
如下文:执行下面方法,数组的依赖函数不会触发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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' ) |
新增代码如下:
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 | 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]); } }<br> //添加对数组里面每一个值进行响应式监听 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); // 递归进行 } } } |
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 | /* * 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; }); }); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具