面试题之vue的响应式
文章目录
- 前言
- 一、响应式是什么?
- 二、Object.defineProperty
- 二、简单模拟vue
- 三、深度监听
- 四、监听数组
- 总结
前言
为了应对面试而进行的学习记录,可能不够有深度甚至有错误,还请各位谅解,并不吝赐教,共同进步。
一、响应式是什么?
我个人的简单理解就是数据在发生变化时候,能自动的执行某些我们需要的操作行为。在vue
中就是我们首次将数据渲染到页面中后,如果我们后面在修改数据,页面中也会自动进行更新,很明显,vue
帮我们完成了响应式。
我们先来讲述vue2的响应式实现。
后面在讲述vue3,因为他们实现的原理有区别。
二、Object.defineProperty
首先我们需要先了解Object.defineProperty()
,这个方法可以帮助我们来劫持对象上面的属性,是实现响应式的核心内容。
我们先来基本使用用下Object.defineProperty()
。
const data = {};let name = 'xiacan';/*** 第一个参数: 要监听的对象* 第二个参数: 要监听的属性* 第三个参数: 一个有get函数和set函数的对象*/Object.defineProperty(data,"name",{get(){console.log("name属性被获取啦!");//返回值 就是我们data[name] 获取到的值return name;},set(value) {// value 就是 我们设置name属性时候赋值的值console.log("name属性被赋新值了:",value);name = value;}})console.log(data.name);data.name = 'xiazai';console.log(data.name);
执行后的结果:
是不是很简单,我们已经完成了对对象属性的监听,当对象被使用和修改时候,我们已经可以做我们需要的操作了。
二、简单模拟vue
上面我们了解了怎么监听对象,我们来简单的模拟一下vue。
//模拟视图更新
function updateView(){console.log("视图更新啦!");
}// 具体进行数据监听的函数
function definePy(target, key, value){Object.defineProperty(target, key, {get() {//直接返回当前值return value;},set(newValue) {//判断是否是修改为新值,否则不更新视图if(newValue === value) return; value = newValue;//更新视图updateView();}})
}//监听数据函数
function observer(target){//判断如果是基本类型就不监听if(typeof target !== 'object' || target === null ) return target;//我们循环对象的所有属性for(let key in target){//监听每个属性 将对象 当前属性 当前属性值传入definePy(target,key,target[key])}}//初始数据
const data = {name: 'xiacan',age: 22
}
//开始监听数据
observer(data)data.name = 'xiazai';
console.log(data.name);
运行截图:
我们这样就成功的简单模拟了vue的响应式。
但是我们还不够,不能对data进行深程度的监听。
三、深度监听
我们将初始数据层级加深:
//初始数据
const data = {name: 'xiacan',age: 22,like:{one:'xi'}
}
//开始监听数据
observer(data)
data.like.one = 'ai';
运行一下:
很明显,并未检测到like对象属性
的变换。
我们进一步优化,能够进行深度监听数据
。
//模拟视图更新
function updateView(){console.log("视图更新啦!");
}// 具体进行数据监听的函数
function definePy(target, key, value){// 进行深度循环observer(target[key]);Object.defineProperty(target, key, {get() {//直接返回当前值return value;},set(newValue) {//判断是否是修改为新值,否则不更新视图if(newValue === value) return;// 进行深度循环,再有新值时候observer(newValue);value = newValue;//更新视图updateView();}})
}//监听数据函数
function observer(target){//判断如果是基本类型就不监听 同时返回if(typeof target !== 'object' || target === null ) return target;//我们循环对象的所有属性for(let key in target){//监听每个属性 将对象 当前属性 当前属性值传入definePy(target,key,target[key]);}}//初始数据
const data = {name: 'xiacan',age: 22,like:{one:'xi',two:'22'}
}
//开始监听数据
observer(data)data.like.one = 'ai';
data.like.two = {a:1
};
data.like.two.a = 2;
运行一下:
我们需要在开始劫持data属性前,将当前属性在进行一次监听就可以实现深度监听了,因为前面我们已经写好了结束的条件就是如果是基本类型就不监听,同时返回,这样就不会死循环。
然后还需要在每次属性赋新值
时候也进行一次进行深度循环,因为可能赋值一个对象,这样我们才能监听变化。
我们还需要进行下一步的优化,就是实现对数组的监听
。
四、监听数组
我们先来看一看对数组进行监听:
//初始数据
const data = {name: 'xiacan',age: 22,like:{one:'xi',two:'22'},num: [1, 2, 3]
}
//开始监听数据
observer(data)data.num[0] = 11
data.num.push(4)
运行一下:
很显然,能监听到数组原来的数据变化,但是执行数组的方法时候未能监听。
我们要实现对数组的监听,我们需要修改一下数组的原型,在原型上定义方法,让我们来实现监听数组的变化。
//模拟视图更新
function updateView(){console.log("视图更新啦!");
}//创建一个新对象,原型执行数组的原型,但是不会干扰原来的原型
const newArr = Object.create(Array.prototype);
//数组方法太多了,我们选几个常见的修改
[ 'push', 'unshift', 'shift', 'pop' ].forEach(newFunName =>{newArr[newFunName] = function () {//更新视图updateView();//执行数组原型上原始的方法Array.prototype[newFunName].call(this, ...arguments)}
})
// 具体进行数据监听的函数
function definePy(target, key, value){// 进行深度循环observer(target[key]);Object.defineProperty(target, key, {get() {//直接返回当前值return value;},set(newValue) {//判断是否是修改为新值,否则不更新视图if(newValue === value) return;// 进行深度循环,再有新值时候observer(newValue);value = newValue;//更新视图updateView();}})
}//监听数据函数
function observer(target){//判断如果是基本类型就不监听 同时返回避免死递归if(typeof target !== 'object' || target === null ) return target;//判断如果是数组,我们就修改原型为我们新建的if (Array.isArray(target)){target.__proto__ = newArr;}//我们循环对象的所有属性for(let key in target){//监听每个属性 将对象 当前属性 当前属性值传入definePy(target,key,target[key]);}}//初始数据
const data = {name: 'xiacan',age: 22,like:{one:'xi',two:'22'},num: [1, 2, 3]
}
//开始监听数据
observer(data)data.num.push(4);
data.num.pop();
运行一下:
我们干嘛要修改数组原型,因为我们不能污染全局的数组原型,所以我们就自己定义一个新的原型,然后在对数组的方法进行修改,在里面添加进入了更新视图的方法,这也是vue中监听数组的实现方法,然后我们在开始监听data数据时候,先进行判断,如果为数组,我们就将当前对象的原型改变为我们新建的原型。
总结
我们已经大致将vue实现响应式简单的模拟了一下了,其中我们可以发现对于对象新增属性和删除属性
我们是无法监听到的,所以vue中有其他的专门方法来完成。对于数组,我们就需要重新修改原型来实现监听。在vue2中对于深度监听是一次不断循环来完成的,如果数据层级多,速度会变得慢。vue3使用proxy后速度会有提高,还支持检测属性的新增和删除,以及监听数组,后续学习后更新文章进行记录。
相关文章:

面试题之vue的响应式
文章目录前言一、响应式是什么?二、Object.defineProperty二、简单模拟vue三、深度监听四、监听数组总结前言 为了应对面试而进行的学习记录,可能不够有深度甚至有错误,还请各位谅解,并不吝赐教,共同进步。 一、响应式…...

聚焦弹性问题,杭州铭师堂的 Serverless 之路
作者:王彬、朱磊、史明伟 得益于互联网的发展,知识的传播有了新的载体,使用在线学习平台的学生规模逐年增长,越来越多学生在线上获取和使用学习资源,其中教育科技企业是比较独特的存在,他们担当的不仅仅是…...

NDK RTMP直播客户端二
在之前完成的实战项目【FFmpeg音视频播放器】属于拉流范畴,接下来将完成推流工作,通过RTMP实现推流,即直播客户端。简单的说,就是将手机采集的音频数据和视频数据,推到服务器端。 接下来的RTMP直播客户端系列ÿ…...

Python3--垃圾回收机制
一、概述 Python 内部采用 引用计数法,为每个对象维护引用次数,并据此回收不在需要的垃圾对象。由于引用计数法存在重大缺陷,循环引用时由内存泄露风险,因此Python还采用 标记清除法 来回收在循环引用的垃圾对象。此外,…...

C/C++开发,认识opencv各模块
目录 一、opencv模块总述 二、opencv主要模块 2.1 opencv安装路径及内容 2.2 opencv模块头文件说明 2.3 成熟OpenCV主要模块 2.4 社区支持的opencv_contrib扩展主要模块 2.5 关于库文件的引用 一、opencv模块总述 opencv的主要能力在于图像处理,尤其是针对二维图…...

【WLSM、FDM状态估计】电力系统状态估计研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

准备2023(2024)蓝桥杯
前缀和 一维前缀和 s[i]s[i-1]a[i]二维前缀和(子矩阵的和) s[i][j]s[i-1][j]s[i][j-1]-s[i-1][j-1]a[i][j] 差分 一维数组 //b是差分数组b[i]c;b[j1]-c;例题 #include<iostream> using namespace std; int n,m; int b[100002],a[100002]; vo…...

剑指 Offer 60. n个骰子的点数
剑指 Offer 60. n个骰子的点数 难度:middle\color{orange}{middle}middle 题目描述 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。 你需要用一个浮点数数组返回答案,其中第 i 个…...

阿里巴巴-淘宝搜索排序算法学习
模型效能:模型结构优化 模型效能:减枝 FLOPS:每秒浮点运算的次数 模型效能:量化 基于统计阈值限定,基于学习阈值限定。 平台效能:一站式DL训练平台 平台效能:搜索模型的系统流程 协同关系…...

〖Python网络爬虫实战⑮〗- pyquery的使用
订阅:新手可以订阅我的其他专栏。免费阶段订阅量1000python项目实战 Python编程基础教程系列(零基础小白搬砖逆袭) 说明:本专栏持续更新中,目前专栏免费订阅,在转为付费专栏前订阅本专栏的,可以免费订阅付费…...

SQL综合查询下
SQL综合查询下 目录SQL综合查询下18、查询所有人都选修了的课程号与课程名题目代码题解19、SQL查询:查询没有参加选课的学生。题目代码20、SQL查询:统计各门课程选修人数,要求输出课程代号,课程名,有成绩人数ÿ…...

全连接层FC
lenet结构: 输入层(Input Layer):接收手写数字的图像数据,通常是28x28的灰度图像。 卷积层1(Convolutional Layer 1):对输入图像进行卷积操作,提取低级别的特征,使用 6 个大小为 5x5 的卷积核进行卷积,得到 6 个输出特征图,激活函数为 Sigmoid。 平均池化层1(Aver…...

图的遍历及连通性
文章目录 图的遍历及连通性程序设计程序分析图的遍历及连通性 【问题描述】 根据输入的图的邻接矩阵A,判断此图的连通分量的个数。 【输入形式】 第一行为图的结点个数n,之后的n行为邻接矩阵的内容,每行n个数表示。其中A[i][j]=1表示两个结点邻接,而A[i][j]=0表示两个结点无…...

DJ3-4 实时调度
目录 3.4.1 实现实时调度的基本条件 1. 提供必要的信息 2. 系统的处理能力强 3. 采用抢占式调度机制 4. 具有快速切换机制 3.4.2 实时调度算法的分类 1. 非抢占式调度算法 2. 抢占式调度算法 3.4.3 常用的几种实时调度算法 1. 最早截止时间优先 EDF(Ea…...

Oracle之PL/SQL游标练习题(三)
游标练习题目1、定义游标:列出每个员工的姓名部门名称并编程显示第10个到第20个记录2、定义游标:从雇员表中显示工资大于3000的记录,只要姓名、部门编号和工资,编程显示其中的奇数记录3、用游标显示所有部门编号与名称,…...

docker运行服务端性能监控系统Prometheus和数据分析系统Grafana
文章目录一、Prometheus的安装和运行1、使用docker拉取镜像2、创建prometheus.yml文件3、启动容器4、查看启动是否成功5、记录安装过程中出现的错误二、Grafana的安装和运行1、使用docker拉取镜像2、创建grafana3、运行grafana4、查看grafana运行日志5、登录grafana一、Prometh…...

【Linux】【应用层】多线程编程
一、线程创建 Linux 中的 pthread_create() 函数用来创建线程,它声明在<pthread.h>头文件中,语法格式如下: int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine) (void *),void *arg);各个参数…...

GameFramework 框架详解之 如何接入热更框架HybridCLR
一.前言 HybridCLR是一个特性完整、零成本、高性能、低内存的近乎完美的c#热更新方案 GameFramework是一个非常出色完整的基于Unity引擎的游戏框架,里面包含了非常多的模块,封装非常完整。 以前市面上的热更大多数都是Lua为主,后来出了一个ILRuntime的C#热更框架,虽然性能…...

全国青少年软件编程(Scratch)等级考试二级考试真题2023年3月——持续更新.....
一、单选题(共25题,共50分) 1. 小猫的程序如图所示,积木块的颜色与球的颜色一致。点击绿旗执行程序后,下列说法正确的是?( ) A.小猫一直在左右移动,嘴里一直说着“抓到了”。 B.小猫会碰到球,然后停止。 C.小猫一直在左右移动,嘴里一直说着“别跑” D.小猫会碰到球,…...

HTML2.1列表标签
列表标签种类 无序列表 有序列表 自定义列表 使用场景:在列表中按照行展示关联性内容。 特点:按照行的形式,整齐显示内容。 一、无序列表 标签名说明ul无序列表整体,用于包裹li标签li表示无序列表的每一项,用于包…...

在 Flutter 多人视频通话中实现虚拟背景、美颜与空间音效
前言 在之前的「基于声网 Flutter SDK 实现多人视频通话」里,我们通过 Flutter 声网 SDK 完美实现了跨平台和多人视频通话的效果,那么本篇我们将在之前例子的基础上进阶介绍一些常用的特效功能,包括虚拟背景、色彩增强、空间音频、基础变声…...

Ambari-web 架构
Ambari-web 使用的前端 Embar.js MVC 框架实现,Embar.js 是一个 TodoMVC 框架,涵盖了单页面应用(single page application)几乎所有的行为 Nodejs 是一个基于 Chrome JavaScript 运行时建立的一个平台,用来方便的搭建…...

对接百思买Best Buy EDI 的注意事项
在此前的文章:《Best Buy Drop Ship(Commerce hub) EDI业务测试常见报错及解决》中,我们介绍了在业务测试过程中遇到的常见报错及解决方案,以下在此基础上进行补充。 数据未能成功发送给Best Buy可能遇到的情况 Best Buy EDI项目传输业务报…...

2023年郑州重点建设项目名单公布,中创“算力数据中心”项目入选!
4月7日,郑州市人民政府网站公布2023年郑州市重点建设项目名单,名单共列项目680个,总投资1.08万亿元,年度计划投资2691亿元。 在创新驱动能力提升项目名单里,中创算力与人民网人民数据(国家大数据灾备中心&a…...

Pytorch 容器 - 1. Module类介绍
目录 1. 基于Module构建自己的网络 2. Module的初始化变量 3. Modules中需要子类 forward() 4. Modules中其他内置函数 1. 基于Module构建自己的网络 torch.nn.Module是所有神经网络模块的基类,如何定义自已的网络: 由于 Module 是神经网络模块的基…...

百度墨卡托坐标转化笔记
一、墨卡托坐标转化 调研了python和java多种实现方式的转换,发现有的不符合需求,原因还没找到。 我是用百度地图返回的poi边界(返回的是墨卡托坐标) 转换的原理没有深入研究,直接拿来用的,测试可行&…...

每日学术速递4.12
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.HC 随着新的“生成代理”论文的发布,LLM刚刚达到了一个重要的里程碑——通过使用 LLM,生成代理能够在受《模拟人生》启发的交互式沙箱中模拟类人行为。代理架构扩展…...

HarmonyOS/OpenHarmony公司级技术开发团队硬件基本配置清单
有朋友公司咨询进入HarmonyOS/OpenHarmony领域,组建技术团队,硬件设备的基本配置应该是怎么样的比较合适?这个是进入鸿蒙开发领域相关配置的第一步,我们以一个基本的团队配置为例说明,供想进入的团队参考。 HarmonyOS/…...

新一代信息技术赋能,安科瑞搭建智慧水务体系的新思路
随着新时期治水方针的逐步落实,水利现代化、智能化建设已开启,物联网、图像识别、数字孪生等新技术的成熟,也为智慧水务体系的搭建提供了技术保障,新时代治水新思路正逐步得到落实。本文对智慧水务的总体架构与包含的建设内容进行…...

37岁测试工程师被裁,120天没找到工作,无奈...
从短期来看,程序员的确算是个不错的工作,薪水也比一般岗位高很多,但是从长远来看,程序员的中年危机会比其他岗位来的更早,很多程序员只有到了35岁左右,才能真正认清楚互联网行业,尤其是被裁之后…...