日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

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

發布時間:2023/12/10 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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中,使用了修改原型鏈的結構的方式來對數組的變化進行攔截.
先看下面的關系

arrArray.prototypeObject.prototype
  • 原本的關系圖示已經描述的很清楚了
  • 我們對pop和push的攔截的原理
  • 實際上是對Array原型上的pop、push方法進行重寫
  • 但是我們不可能直接在這個原型上重寫(因為有些數組的實例,并不需要響應式).
  • 因此我們在arr和Array.prototype之間添加一層arr_methods,改進后的關系如下
arrarr_methodsArray.prototypeObject.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)} })

總結

以上是生活随笔為你收集整理的javascript --- vue2.x中原型的使用(拦截数组方法) 响应式原理(部分)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。