Vue2源码分析-day2

news/2025/2/11 3:11:45/

实现数组的响应式原理

首先我们在index.html中定义一个数组,并且打印实例

const vm = new MVue({data() {return {name: "zhangsan",age: "16",hobby:['zhangsan','lisi']}}
})
console.log(vm);

我们会发现定义的数组每一项都有get和set方法虽然数组是被劫持了但是这样做性能非常差。如果说数组元素有1000个或者10000个能?那么我们要循环劫持1000次或者10000次吗?这显然是不合理的,所以我们对数组要单独做数据劫持。

在这里插入图片描述
数组一般用户都是push,pop这所方法去操作数组元素所以,我们要重写这些方法。

首先我们先判断是否为数组,obseve/index.js文件下Observer类修改如下代码

constructor(data) {/* 这里注意,Object.defineProperty只能劫持已经存在的属性,新增或删除的无法劫持这也是为什么vue2中新增了,$set和$delete方法这类方法的原因*/if(Array.isArray(data)){// 重写原型对象上的方法data.__proto__=new_array_proto// 劫持数组this.observe_array(data)}else{// 劫持对象this.walk(data)}}
walk(data) {// 循环对象keys依次劫持,重新定义属性Object.keys(data).forEach(key => {define_reactive(data, key, data[key])})
}
observe_array(data){// 如果数组中包含对象,则走对象劫持data.forEach((item)=>observe(item))
}

observe/index.js文件下创建array.js文件用来重写数组方法。并且导出new_array_proto


// 获取原数组原型对象
const old_arr_proto=Array.prototype;// 拷贝新原型对象
export let new_array_proto=Object.create(old_arr_proto);// 定义所以变异方法
let methods=['push','pop','shift','unshift','reverse','sort','splice'];methods.forEach((item)=>{   new_array_proto[item]=function(...args){console.log(123);// 调用原原型上的方法let res=old_arr_proto[item].call(this,...args);return res}
})

然后我们在index.html调用push方法看看控制台是否打印123。如果打印就说明重写成功

在这里插入图片描述

下面我们来对我们的变异方法做进一步处理。因为新增的属性并没有被劫持


// 获取原数组原型对象
const old_arr_proto=Array.prototype;// 拷贝新原型对象
export let new_array_proto=Object.create(old_arr_proto);// 定义所以变异方法
let methods=['push','pop','shift','unshift','reverse','sort','splice'];methods.forEach((item)=>{   new_array_proto[item]=function(...args){// 调用原原型上的方法let res=old_arr_proto[item].call(this,...args);//对新增的属性进行观测let val;switch(item){case "push":case "unshift":val=args;break;case "splice":val=args.slice(2);break;}// this为当前变异方法的调用者。_ob_为观测类的实例if(val){this._ob_.observe_array(val)		// 可能到这里你会好奇这个_ob_是哪里来的。别急下面我将解释}return res}
})

observe/index.js文件下中构造函数增加如下代码。添加_ob_一方面是为了给已经观测的数据打上标识,另一方便是为了调用数组的变异方法时如果新增的是对象那么,通过_ob_获取到观测类实例对这个新增对象进行观测

    constructor(data) {/* 这里注意,Object.defineProperty只能劫持已经存在的属性,新增或删除的无法劫持这也是为什么vue2中新增了,$set和$delete方法这类方法的原因*/// 对即将观测的数据添加_ob_属性。添加被观测标识Object.defineProperty(data, '_ob_', {value:this,enumerable:false    // 禁止枚举,防止死循环})if(Array.isArray(data)){// 重写原型对象上的方法data.__proto__=new_array_proto// 劫持数组this.observe_array(data)}else{// 劫持对象this.walk(data)}}

既然已经被观测的数据打上了表示,那么为了防止重复观测我们就可以在observe方法中添加如下代码

 // 对对象劫持if (typeof data !== 'object' || data === null) {return;}// 如果已经被检测过直接返回if(data._ob_ instanceof Observer){return data._ob_}// 如果一个对象被劫持过就不需要再次劫持,我们可以通过一个实例判断是否被劫持过return new Observer(data)

下面我们在index.html文件下push一个对象就可以看到这个对象也被观测到了

在这里插入图片描述


http://www.ppmy.cn/news/1016970.html

相关文章

【工作中问题解决实践 十】一次内存泄露排查-MAT使用指南

最近体验了一把当医生的感觉,定位病根病因,感觉这种要揪出问题的感觉很爽,并不觉得麻烦,这里将整个排查过程记录一下,方便之后再遇到类似问题有应对之道。 问题背景 2023-07-18 早上还在睡梦中的俺被一条条报警消息铛…

人工智能学习1——特征提取和距离

强人工智能和弱人工智能: 强人工智能:和人脑一样 弱人工智能:不一定和人脑思考方式一样,但是可以达到相同的效果,弱人工智能并不弱 —————————————————————————————————— 机器学习能…

kubernetes部署milvus

milvus介绍 Milvus创建于2019年,其唯一目标是存储、索引和管理由深度神经网络和其他机器学习(ML)模型生成的大量嵌入向量。 嵌入向量数据库Milvus是一种专门为处理输入向量查询而设计的数据库,能够在万亿规模上对向量进行索引。与…

【FAQ】视频监控EasyCVR平台登录密码忘记?如何通过navicat连接数据库进行修改?

TSINGSEE青犀视频监控管理平台EasyCVR可以根据不同的应用场景需求,让平台在内网、专网、VPN、广域网、互联网等各种环境下进行音视频的采集、接入与多端分发。在视频能力上,平台可实现视频实时直播、云端录像、云存储、回放与检索、告警上报、视频快照、…

PS透明屏,在科技展示中,有哪些优点展示?

PS透明屏是一种新型的显示技术,它将传统的显示屏幕与透明材料相结合,使得屏幕能够同时显示图像和透过屏幕看到背后的物体。 这种技术在商业展示、广告宣传、产品展示等领域有着广泛的应用前景。 PS透明屏的工作原理是利用透明材料的特性,通…

zju代码题:4-6

一 分段函数算水费 #include <stdio.h>int main() {/*** 定义两个* 定义浮点型变量* y:水费* x:用水的吨数* */double x, y;printf("Enter x(x>=0):\n"

IMv9.0版本总结[服务端+客户端],最终版本

一、经历的版本 经历了多个版本&#xff0c;基础内容在前面&#xff0c;可以使用之前的基础环境&#xff1a; v1&#xff1a; https://blog.csdn.net/wtt234/article/details/132139454 v2&#xff1a; https://blog.csdn.net/wtt234/article/details/132144907 v3&#xff1a;…

企业举办活动邀请媒体的意义和重要性

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 企业举办活动并邀请媒体的意义和重要性是多方面的&#xff0c;主要有以下一些&#xff1a; 1. 品牌曝光与宣传&#xff1a;邀请媒体参与企业活动可以提高企业的品牌曝光度。媒体报道能够…