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.pswp.cn/news/250264.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250264.shtml
英文地址,請注明出處:http://en.pswp.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…

javascript --- 手寫Promise、快排、冒泡、單例模式+觀察者模式

手寫promise 一種異步的解決方案, 參考 Promise代碼基本結構 function Promise(executor){this.state pending;this.value undefined;this.reason undefined;function resolve(){}function reject(){} } module.exports Promisestate保存的是當前的狀態,在Promise狀態發…

PyCharm 通過Github和Git上管理代碼

1.Pycharm中設置如圖: 2.配置Git,通過網頁 https://www.git-scm.com/download/win 下載 3. 轉載于:https://www.cnblogs.com/0909/p/9956406.html

【BZOJ】2395: [Balkan 2011]Timeismoney

題解 最小乘積生成樹&#xff01; 我們把&#xff0c;x的總和和y的總和作為x坐標和y左邊&#xff0c;畫在坐標系上 我們選擇兩個初始點&#xff0c;一個是最靠近y軸的A&#xff0c;也就是x總和最小&#xff0c;一個是最靠近x軸的B&#xff0c;也就是y總和最小 連接兩條直線&…

http --- http與https相關概念小結

網絡協議 參考 HTTP的特性 HTTP協議構建于TCP/IP協議之上,是一個應用層協議,默認端口是80HTTP是無連接無狀態的 HTTP報文 請求報文 HTTP協議是以ASCII碼傳輸,建立在 TCP/IP 協議之上的應用層規范。規范把HTTP請求分為三個部分:狀態行、請求頭、消息主體。 <method>…

Spring AOP注解方式實現

簡介 上文已經提到了Spring AOP的概念以及簡單的靜態代理、動態代理簡單示例&#xff0c;鏈接地址&#xff1a;https://www.cnblogs.com/chenzhaoren/p/9959596.html 本文將介紹Spring AOP的常用注解以及注解形式實現動態代理的簡單示例。 常用注解 aspect&#xff1a;定義切面…

享元模式-Flyweight(Java實現)

享元模式-Flyweight 享元模式的主要目的是實現對象的共享,即共享池,當系統中對象多的時候可以減少內存的開銷,通常與工廠模式一起使用。 本文中的例子如下: 使用享元模式: 小明想看編程技術的書, 就到家里的書架上拿, 如果有就直接看, 沒有就去買一本, 回家看. 看完了就放到家里…

算法 --- 回溯法

回溯法 參考 - 劍指Offer 回溯法可以看成蠻力法的升級版,它從解決問題每一步的所有可能選項里系統地選擇出一個可行的解決方案. 回溯法解決的問題的特性: 可以形象地用樹狀結構表示: 節點: 算法中的每一個步驟節點之間的連接線: 每個步驟中的選項,通過每一天連接線,可以到達…

013.Zabbix的Items(監控項)

一 Items簡介 Items是從主機里面獲取的所有數據&#xff0c;可以配置獲取監控數據的方式、取值的數據類型、獲取數值的間隔、歷史數據保存時間、趨勢數據保存時間、監控key的分組等。通常情況下item由key參數組成&#xff0c;如監控項中需要獲取cpu信息&#xff0c;則需要一個對…

Cookie 和 Session的區別

pass 下次再寫轉載于:https://www.cnblogs.com/nieliangcai/p/9073520.html

算法 --- 記一道面試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]題目要求不使用除法,且時間…

編碼

一、什么是編碼&#xff1f;首先&#xff0c;我們從一段信息即消息說起&#xff0c;消息以人類可以理解、易懂的表示存在。我打算將這種表示稱為“明文”&#xff08;plain text&#xff09;。對于說英語的人&#xff0c;紙張上打印的或屏幕上顯示的英文單詞都算作明文。其次&a…

ASP.NET MVC 實現頁落網資源分享網站+充值管理+后臺管理(10)之素材管理

源碼下載地址&#xff1a;http://www.yealuo.com/Sccnn/Detail?KeyValuec891ffae-7441-4afb-9a75-c5fe000e3d1c 素材管理模塊也是我們這個項目的核心模塊&#xff0c;里面的增刪查改都跟文章管理模塊相同或者相似&#xff0c;唯一不同點可能是對附件的上傳處理&#xff0c;但…

javascript --- [express+ vue2.x + elementUI]登陸的流程梳理

說明 涉及到以下知識點: 登陸的具體流程express、vue2.x、elementUI、axios、jwt、assert 登陸方面的API使用中間件的使用前后端通過http狀態碼,進行響應的操作(這里主要是401)密碼驗證(bcrypt的hashSync方法對明文密碼進行加密,compareSync方法對加密的密碼進行驗證)token的…

設計模式---裝飾模式

今天學習了裝飾模式&#xff0c;做個筆記。。裝飾模式的基礎概念可以參考&#xff1a;https://blog.csdn.net/cjjky/article/details/7478788 這里&#xff0c;就舉個簡單例子 孫悟空有72變&#xff0c;但是它平時是猴子&#xff0c;遇到情況下&#xff0c;它可以變成蝴蝶等等 …

springMvc 注解@JsonFormat 日期格式化

1&#xff1a;一定要加入依賴,否則不生效&#xff1a; <!--日期格式化依賴--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version>&…

Git很簡單--圖解攻略

Git Git 是目前世界上最先進的分布式版本控制系統&#xff08;沒有之一&#xff09;作用 源代碼管理為什么要進行源代碼管理? 方便多人協同開發方便版本控制Git管理源代碼特點 1.Git是分布式管理.服務器和客戶端都有版本控制能力,都能進行代碼的提交、合并、. 2.Git會在根…

css --- 使用scss生成常用的基本css樣式

"工具樣式"的概念和 SASS(SCSS) 在webpack中使用sass 安裝sass和sass-loader $ npm i sass sass-loader由于使用了腳手架,安裝完畢后重啟前端即可 樣式重置 其實就是樣式的初始化 // reset* {box-sizing: border-box; // 以邊框為準. css3盒模型outline: none;…

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…