Vue2源码分析-day2

实现数组的响应式原理

首先我们在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.rhkb.cn/news/81610.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线程池-手写线程池C++11版本(生产者-消费者模型)

本项目是基于C11的线程池。使用了许多C的新特性,包含不限于模板函数泛型编程、std::future、std::packaged_task、std::bind、std::forward完美转发、std::make_shared智能指针、decltype类型推断、std::unique_lock锁等C11新特性功能。 本项目有一定的上手难度。推…

计算机网络—TCP

这里写目录标题 TCP头格式有哪些为什么需要TCP,TCP工作在哪什么是TCP什么是TCP连接如何确定一个TCP连接TCP和UDP的区别,以及场景TCP和UDP能共用一个端口?TCP的建立TCP三次握手过程为什么是三次握手、不是两次、四次why每次建立连接&#xff0…

3.1 计算机网络和网络设备

数据参考:CISP官方 目录 计算机网络基础网络互联设备网络传输介质 一、计算机网络基础 1、ENIAC:世界上第一台计算机的诞生 1946年2月14日,宾夕法尼亚大学诞生了世界上第一台计算机,名为电子数字积分计算机(ENIAC…

Netty框架自带类DefaultEventExecutorGroup的作用,用来做业务的并发

一、DefaultEventExecutorGroup的用途 DefaultEventExecutorGroup 是 Netty 框架中的一个类,用于管理和调度事件处理器(EventExecutor)的组。在 Netty 中,事件处理是通过多线程来完成的,EventExecutor 是处理事件的基…

2023年中期奶粉行业分析报告(京东数据开放平台)

根据国家统计局和民政部数据公布,2022年中国结婚登记数创造了1980年(有数据公布)以来的历史新低,共计683.3万对。相较于2013年巅峰时期的数据,2022年全国结婚登记对数已接近“腰斩”。 2023年“520”期间的结婚登记数…

【MySQL】

这里写目录标题 MySQL架构一条sql执行流程MySQL数据存放电脑位置ibd文件结构行溢出是什么MySQL行记录存储格式索引为什么InnoDB选择B树作为索引数据结构什么时候需要创建索引优化索引方法InnoDB内部怎么存储数据B 树如何进行查询聚簇索引和二级索引为什么MySQL要采用B树作为索引…

【Spring Boot】Spring Boot项目的创建和文件配置

目录 一、为什么要学Spring Boot 1、Spring Boot的优点 二、创建Spring Boot项目 1、创建项目之前的准备工作 2、创建Spring Boot项目 3、项目目录的介绍 4、安装Spring Boot快速添加依赖的插件 5、在项目中写一个helloworld 三、Spring Boot的配置文件 1、配置文件的…

ELK 企业级日志分析系统(二)

目录 ELK Kiabana 部署(在 Node1 节点上操作) 1.安装 Kiabana 2.设置 Kibana 的主配置文件 3.启动 Kibana 服务 4.验证 Kibana 5.将 Apache 服务器的日志(访问的、错误的&#x…

知识图谱实战应用23-【知识图谱的高级用法】Neo4j图算法的Cypher查询语句实例

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用23-【知识图谱的高级用法】Neo4j图算法的Cypher查询语句实例,Neo4j图算法是一套在Neo4j图数据库上运行的算法集合。这些算法专门针对图数据结构进行设计,用于分析、查询和处理图数据。图算法可以帮助我们发现图中的模…

【Azure】office365邮箱测试的邮箱账号因频繁连接邮箱服务器而被限制连接 引起邮箱显示异常

azure微软office365邮箱会对频繁连接自身邮箱服务器的IP地址进行,连接邮箱服务器IP限制,也就是黑名单,释放时间不确定,但至少一天及以上。 解决办法,换一个IP,或者新注册一个office365邮箱再重试。 以下是…

使用 API Gateway Integrator 在 Quarkus 中实施适用于 AWS Lambda 的 OpenAPI

AWS API Gateway 集成使得使用符合 OpenAPI 标准的 Lambda Function 轻松实现 REST API。 关于开放API 它是一个 允许以标准方式描述 REST API 的规范。 OpenAPI规范 (OAS) 为 REST API 定义了与编程语言无关的标准接口描述。这使得人类和计算机都可以发现和理解服务的功能&am…

中介者模式(C++)

定义 用一个中介对象来封装(封装变化)一系列的对象交互。中介者使各对象不需要显式的相互引用(编译时依赖->运行时依赖),从而使其耦合松散(管理变化),而且可以独立地改变它们之间的交互。 应用场景 在软件构建过程中,经常会出现多个对象…

漫画算法做题笔记

诸神缄默不语-个人CSDN博文目录 哦这是我三年前写的,我现在Java语法都快忘光了…… 反正之前的博文也发一下好了。这个因为我当年是用有道云笔记而不是直接用CSDN编辑器写的,所以后面有些内容写乱了,因为我现在猛的一看有点看不懂&#xff0…

C++11之右值引用

C11之右值引用 传统的C语法中就有引用的语法,而C11中新增了的 右值引用(rvalue reference)语法特性,所以从现在开始我们之前学习的引用就叫做左值引用(lvalue reference)。无论左值引用还是右值引用&#…

【TypeScript】初识TypeScript和变量类型介绍

TypeScript 1,TypeScript是什么?2,类型的缺失带来的影响3,Ts搭建环境-本博主有专门的文章专说明这个4,使用tsc对ts文件进行编译5,TS运行初体验简化Ts运行步骤解决方案1解决方案2(常见) 开始学习…

Apache Paimon 学习笔记

本博客对应于 B 站尚硅谷教学视频 尚硅谷大数据Apache Paimon教程(流式数据湖平台),为视频对应笔记的相关整理。 1 概述 1.1 简介 Flink 社区希望能够将 Flink 的 Streaming 实时计算能力和 Lakehouse 新架构优势进一步结合,推…

Centos更换网卡名称为eth0

Centos更换网卡名称为eth0 已安装好系统后需要修改网卡名称为eth0 编辑配置文件将ens33信息替换为eth0,可在vim命令模式输入%s/ens33/eth0/g替换相关内容 修改内核文件,添加内容:net.ifnames=0 biosdevname=0 [root@nova3 ~]# vim /etc/default/grub 使用命令重新生成g…

【JAVA】有关时间的操作在编程中如何实现?

个人主页:【😊个人主页】 系列专栏:【❤️初识JAVA】 文章目录 前言Date 类Date 类方法Data的缺陷实例获取当前日期时间日期比较java中设置date数据的显示格式 前言 在许多应用程序中,日期和时间的处理是必不可少的。Java提供了一…

用Shap-E生成3D模型

Shap-E 是 OpenAI 开发的突破性模型,它使用文本或图像作为输入生成一系列 3D 对象,以其创新方法改变了 3D 应用领域。 这项非凡的技术可以在 GitHub 上免费获取,允许用户在计算机上无缝运行它,而无需 OpenAI API 密钥或互联网连接…