javascript --- vue2.x中原型的使用(拦截数组方法) 响应式原理(部分)

说明

在Vue2.x中,利用了对原型链的理解,巧妙的利用JavaScript中的原型链,实现了数组的pop、push、shift、unshift、reverse、sort、splice等的拦截.

你可能需要的知识

  • 参考 - MDN

原型链

JavaScript常被描述为一种基于原型的语言(prototype-based language),每个对象拥有一个原型.
数组类型也不例外.验证如下:

let arr = [];
console.log(arr)
/*{length: 0__proto__: {length: 0constructor: f Array()...__proto__: Object}}
*/

可见数组的原型是继承于Object。

响应式

参考 - MDN
响应式的核心是使用Object.defineProperty在对数据进行读取或者写入时进行劫持操作.

let o = {}
,_gender
Object.defineProperty(o, gender, {get(){return _gender},set(newVal){_gender = newVal}	
})

对一个属性,同时使用get和set方法时,需要一个中间变量取存储,否则会造成循环使用.

Vue 2.x中的响应式

  • Vue在使用过程中,可能会用到很多的变量,而每把一个数据进行响应式化,就需要一个变量去存储.这样有可能会污染全局作用域.
  • Vue中采取的方法是使用函数的形参,来实现响应式,实现如下
function defineReactive(target, key, value, enumerable){// 注意: 此处的value与上文的_gender类型Object.defineProperty(target, key, {configurable: true,enumerable: !!enumerable,get(){console.log(`读取${value}`)return value},set(newVal){console.log(`写入: ${value} --> ${newVal}`)value = newVal}})
}
let o = {name: 'marron',age: 26,remark: 'hunt for job'
}
Object.keys(o).forEach(k => {defineReactive(o,k,o[k],true)
})

在这里插入图片描述
以上实现了对数据的拦截: 即对数据进行 写入/读取 操作时,会按照一定规则优先执行某些步骤.
但是以上代码还存在一些小小的瑕疵

对象深层次

以上代码不对对象的深层次进行响应式化,如下面数据

let o = {list: [ { person1: {name:'Marron',age: 18}},{person2: {name:'Mar',age: 25}}]
}

在这里插入图片描述
此时,需要考虑数组,和对象的子元素问题.
对于数组问题,我们修改遍历,如果是数组,则取出数组中的每个元素,进行添加响应式处理

- Object.keys(o).forEach(k =>{
- 	defineReactive(o, k, o[k], true)
- })
+ function reactify(o){
+ 	Object.keys(o).forEach(k => {
+ 		if(Array.isArray(o[k])){
+ 			o[k].forEach(val => reactive(val))
+ 		} else {
+ 			defineReactive(o, k, o[k], true)
+ 		}
+ })}

对于深层次对象问题,我们对defineReactive进行修改

function defineReactive(o, key, value, enumerable){if(typeof value =='object' && value !== null && !Array.isArray(value)){// 此处可以认为是对象reactify(value)}// 此处是最后一层,添加响应式Object.defineProperty(o, key, {configurable: true,enumerable: !!enumerable,get(){console.log(`读取${key}`)return value},set(newVal){console.log(`写入${key} => ${newVal}`)value = newVal}})
}

在这里插入图片描述

Vue2.x对数组部分方法的拦截

上面的响应式无法对数组的pop、push等方法进行响应
在这里插入图片描述
在Vue2.x中,使用了修改原型链的结构的方式来对数组的变化进行拦截.
先看下面的关系

arr
Array.prototype
Object.prototype
  • 原本的关系图示已经描述的很清楚了
  • 我们对pop和push的拦截的原理
  • 实际上是对Array原型上的pop、push方法进行重写
  • 但是我们不可能直接在这个原型上重写(因为有些数组的实例,并不需要响应式).
  • 因此我们在arrArray.prototype之间添加一层arr_methods,改进后的关系如下
arr
arr_methods
Array.prototype
Object.prototype

【具体的实现思路】:
先创建一个arr_methods对象其原型是Array.prototype.然后修改arr_methods上需要拦截的方法(存储在数组ARRAY_METHOD中)

const ARRAY_METHOD = ['push','pop','shift','unshift','reverse','sort','splice'
]
let arr_methods = Object.create(Array.prototype)ARRAY_METHOD.forEach(method=>{arr_methods[method] = function(){// 拦截的函数console.log(`调用${method}方法`)	return Array.prototype[method].apply(this, arguments)}
})
arr.__proto__ = arr_methods

在这里插入图片描述
此时既不影响原生的Array.prototype,又实现了对pop、push...方法的拦截,完成之后只需要修改前面的方法.即可完成对数组pop、push方法的拦截

 function reactify(o){Object.keys(o).forEach(k => {if(Array.isArray(o[k])){// 数组方法的响应式o[k].__proto__ = array_method
. 			o[k].forEach(val => reactive(val))} else {defineReactive(o, k, o[k], true)}})}

最后,此时只是拦截,还差一步形成响应式

ARRAY_METHOD.forEach(method=>{arr_methods[method] = function(){// 拦截的函数console.log(`调用${method}方法`)for(let i =0, len = arugments.length; i < len; i++){reactify(arguments[i])}return Array.prototype[method].apply(this, arguments)}
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250264.shtml

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

相关文章

dubbo-admin构建报错

dubbo-admin构建报错 意思是maven库里没有dubbo2.5.4-SNAPSHOT.jar这个版本的dubbo的jar包&#xff0c;把dubbo-admin项目的pom.xml的   <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>${proje…

PyCharm 通过Github和Git上管理代码

1.Pycharm中设置如图: 2.配置Git,通过网页 https://www.git-scm.com/download/win 下载 3. 转载于:https://www.cnblogs.com/0909/p/9956406.html

享元模式-Flyweight(Java实现)

享元模式-Flyweight 享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。 本文中的例子如下: 使用享元模式: 小明想看编程技术的书, 就到家里的书架上拿, 如果有就直接看, 没有就去买一本, 回家看. 看完了就放到家里…

013.Zabbix的Items(监控项)

一 Items简介 Items是从主机里面获取的所有数据&#xff0c;可以配置获取监控数据的方式、取值的数据类型、获取数值的间隔、历史数据保存时间、趋势数据保存时间、监控key的分组等。通常情况下item由key参数组成&#xff0c;如监控项中需要获取cpu信息&#xff0c;则需要一个对…

算法 --- 记一道面试dp算法题

题目: 给定一个数组(长度大于1),如下 let a [1,4,3,4,5] // 长度不确定,数值为整数要求写一个函数,返回该数组中,除本身数字之外其他元素的成积.即返回如下: // 过程[4*3*4*5, 1*3*4*5, 1*4*4*5, 1*4*3*5, 1*4*3*4] // 结果[240, 60, 80, 60, 48]题目要求不使用除法,且时间…

ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(10)之素材管理

源码下载地址&#xff1a;http://www.yealuo.com/Sccnn/Detail?KeyValuec891ffae-7441-4afb-9a75-c5fe000e3d1c 素材管理模块也是我们这个项目的核心模块&#xff0c;里面的增删查改都跟文章管理模块相同或者相似&#xff0c;唯一不同点可能是对附件的上传处理&#xff0c;但…

Git很简单--图解攻略

Git Git 是目前世界上最先进的分布式版本控制系统&#xff08;没有之一&#xff09;作用 源代码管理为什么要进行源代码管理? 方便多人协同开发方便版本控制Git管理源代码特点 1.Git是分布式管理.服务器和客户端都有版本控制能力,都能进行代码的提交、合并、. 2.Git会在根…

vc/vs开发的应用程序添加dump崩溃日志转

原贴地址&#xff1a;https://blog.csdn.net/wangkui1331/article/details/78029940 vc/vs开发的应用程序出现崩溃的时候&#xff0c;由于没有任何记录&#xff0c;导致开发人员很难追踪&#xff0c;但是添加dump文件后&#xff0c;就可以免除这些烦恼 1.添加方法 &#xff08;…

51 nod 1127最短的包含字符串(尺取法)

1127 最短的包含字符串 收藏关注给出一个字符串&#xff0c;求该字符串的一个子串S&#xff0c;S包含A-Z中的全部字母&#xff0c;并且S是所有符合条件的子串中最短的&#xff0c;输出S的长度。如果给出的字符串中并不包括A-Z中的全部字母&#xff0c;则输出No Solution。Input…

JSON 数据重复 出现$ref

JSONArray 类型 如果我们往里面add数据的时候 如果数据相同&#xff0c;那么就会被替换成 $ref: 也就是被简化了 因为数据一样所直接 指向上一条数据 循环引用&#xff1a;当一个对象包含另一个对象时&#xff0c;fastjson就会把该对象解析成引用。引用是通过$ref标示的&am…

Linux初学时的一些常用命令(4)

1. 磁盘 查看当前磁盘使用情况 df -h查看某个文件大小 du -sh 文件名 如果不输入文件名&#xff0c;默认是当前目录的所有文件之和&#xff0c;即当前目录大小 2. 系统内存 free参数详解&#xff1a;https://blog.csdn.net/loongshawn/article/details/51758116 3. CPU CPU 使用…

爬虫之拉勾网职位获取

重点在于演示urllib.request.Request()请求中各项参数的 书写格式 譬如&#xff1a; url data headers...Demo演示&#xff08;POST请求&#xff09;:import urllib.requestimport urllib.parseimport json, jsonpath, csvurl "https://www.lagou.com/jobs/positionAjax.…

小程序 --- 点击放大功能、获取位置信息、文字样式省略、页面跳转(navigateTo)

1. 点击放大功能的实现 需求: 点击轮播图中的图片会实现放大预览的功能。首先有轮播图的样式如下 <!-- pages/goods_detail/index.wxml --> <!-- 轮播图 --> <view class"detail_swiper"><swiperautoplaycircularindicator-dots><swip…

Axure实现多用户注册验证

*****多用户登录验证***** 一、&#xff08;常规想法&#xff09;方法&#xff1a;工作量较大&#xff0c;做起来繁琐 1、当用户名和密码相同时怎么区分两者&#xff0c;使用冒号和括号来区分&#xff1a; eg. (admin:123456)(123456:demo)(zhang:san);由此得出前面是括号后面是…

Maximum Xor Secondary(单调栈好题)

Maximum Xor Secondary CodeForces - 280B Bike loves looking for the second maximum element in the sequence. The second maximum element in the sequence of distinct numbers x1, x2, ..., xk (k > 1) is such maximum element xj, that the following inequa…

杂项-公司:唯品会

ylbtech-杂项-公司&#xff1a;唯品会唯品会公司成立于2008年08月&#xff0c;2012年3月23日登陆美国纽约证券交易所上市&#xff08;股票代码&#xff1a;VIPS&#xff09;。成为华南第一家在美国纽交所上市的电子商务企业。主营B2C商城唯品会名牌折扣网站是一家致力于打造中高…

Linux基本的操作

一、为什么我们要学习Linux 相信大部分人的PC端都是用Windows系统的&#xff0c;那我们为什么要学习Linux这个操作系统呢&#xff1f;&#xff1f;&#xff1f;Windows图形化界面做得这么好&#xff0c;日常基本使用的话&#xff0c;学习成本几乎为零。 而Linux不一样&#xff…

汇编语言 实验4

实验4 实验内容1&#xff1a;综合使用 loop,[bx]&#xff0c;编写完整汇编程序&#xff0c;实现向内存 b800:07b8 开始的连续 16 个 字单元重复填充字数据 0403H&#xff1b;修改0403H为0441H&#xff0c;再次运行 步骤1&#xff1a;在记事本中编写好temp.asm文件 步骤2&#x…

LDAP第三天 MySQL+LDAP 安装

https://www.easysoft.com/applications/openldap/back-sql-odbc.html OpenLDAP 使用 SQLServer 和 Oracle 数据库。 https://www.cnblogs.com/bigbrotherer/p/7251372.html          CentOS7安装OpenLDAPMySQLPHPLDAPadmin 1.安装和设置数据库 在CentOS7下&…

Myeclipse连接Mysql数据库时报错:Error while performing database login with the pro driver:unable...

driver template: Mysql connector/j&#xff08;下拉框进行选择&#xff09; driver name: 任意填&#xff0c;最好是数据库名称&#xff0c;方便查找 connection URL: jdbc:mysql://localhost:3306/programmableweb User name: 用户名 password: 密码 Driver jars: 添加jar包…