vue2源码-三、数组的劫持
数组的劫持
数组劫持的思路
对于数组劫持的目标是实现数组的响应式:
在
Vue
中,我们很少会使用索引进行操作数组,并且认为有七个方法能够改变数组:
push
、pop
、splice
、unshift
、reverse
,sort
。所以,需要对七个方法进行特殊处理,是他们能够劫持到数组的数据变化,就能够实现数组的响应式。因此,要单独处理,在
Observer
初始化时会walk
遍历属性实现递归;所以就需要将数组响应式的处理逻辑单独出来,重写这个七个方法:
import { arrayMethods } from "./array"; class Observer { constructor(value) { if(isArray(value)){ // 对数组类型进行单独处理:重写 7 个变异方法 }else{ this.walk(value); } } }
数组的重写的注意
数组重写不能影响非响应式数组。
所以,对响应式数据中数组的这七个方法进行拦截:优先从链上查找到并使用重写方法啊,其他方法依然走原生逻辑。
// 希望重写数组中的部分方法 let oldArrayProto = Array.prototype; // newArrayProto.__proto__ = oldArrayProto export let newArrayProto = Object.create(oldArrayProto); // 找到所有的变异方法 let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"]; methods.forEach((method) => { // arr.push(1,2,3) newArrayProto[method] = function (...args) { // 重写了方法 // push.call(arr) const result = oldArrayProto[method].call(this, ...args); // 内部调用原来的方法,函数的劫持,切片编程 // 新增的数据进行劫持 let inserted; // 后面的 let ob = this.__ob__; switch (method) { case "push": inserted = args; break; case "unshift": inserted = args; break; case "splice": inserted = args.slice(2); break; default: break; } if (inserted) { // 对新增的内容进行观测 ob.observeArray(inserted); } // 后面的 ob.dep.notify(); return result; }; });
- 首先,拿到数组的所有原生方法
oldArrayProto
,通过Object.create
原型继承放到arrayMethods
原型链上,相当于将原生方法向后移动了一层。- 当
value
为数组类型时,修改数组的原型链为arrayMethods
;此时,原本在value.__propto__
上原生方法。- 在
arrayMrthods
进行处理,在第一层对7个变异方法进行重写,利用js
原型链查找机制,就实现了对原生方法的拦截。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!