成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

淺析vue偵測數據的變化之基本實現

瀏覽:57日期:2022-09-28 18:29:54
目錄一、Object的變化偵測二、關于 Object 的問題三、Array 的變化偵測3.1、背景3.2、實現四、關于 Array 的問題一、Object的變化偵測

下面我們就來模擬偵測數據變化的邏輯。

強調一下我們要做的事情:數據變化,通知到外界(外界再做一些自己的邏輯處理,比如重新渲染視圖)。

開始編碼之前,我們首先得回答以下幾個問題:

1.如何偵測對象的變化?

使用 Object.defineProperty()。讀數據的時候會觸發 getter,修改數據會觸發 setter。 只有能偵測對象的變化,才能在數據發生變化的時候發出通知

2.當數據發生變化的時候,我們通知誰?

通知用到數據的地方。而數據可以用在模板中,也可以用在 vm.$watch() 中,地方不同,行為也不相同,比如這里要渲染模板,那里要進行其他邏輯。所以干脆抽象出一個類。當數據變化的時候通知它,再由它去通知其他地方。 這個類起名叫 Watcher。就是一個中介。

3.依賴誰?

通知誰,就依賴誰,依賴 Watcher。

4.何時通知?

修改數據的時候。也就是 setter 中通知

5.何時收集依賴?

因為要通知用數據的地方。用數據就得讀數據,我們就可以在讀數據的時候收集,也就是在 getter 中收集

6.收集到哪里?

可以在每個屬性里面定義一個數組,與該屬性有關的依賴都放里面

編碼如下(可直接運行):

// 全局變量,用于存儲依賴let globalData = undefined;// 將數據轉為響應式function defineReactive (obj,key,val) { // 依賴列表 let dependList = [] Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function () {// 收集依賴(Watcher)globalData && dependList.push(globalData)return val }, set: function reactiveSetter (newVal) {if(val === newVal){ return}// 通知依賴項(Watcher)dependList.forEach(w => { w.update(newVal, val)})val = newVal } });}// 依賴class Watcher{ constructor(data, key, callback){this.data = data;this.key = key;this.callback = callback;this.val = this.get(); } // 這段代碼可以將自己添加到依賴列表中 get(){// 將依賴保存在 globalDataglobalData = this;// 讀數據的時候收集依賴let value = this.data[this.key]globalData = undefinedreturn value; } // 數據改變時收到通知,然后再通知到外界 update(newVal, oldVal){this.callback(newVal, oldVal) }}/* 以下是測試代碼 */let data = {};// 將 name 屬性轉為響應式defineReactive(data, ’age’, ’88’)// 當數據 age 改變時,會通知到 Watcher,再由 Watcher 通知到外界new Watcher(data, ’age’, (newVal, oldVal) => { console.log(`外界:newVal = ${newVal} ; oldVal = ${oldVal}`)})data.age -= 1 // 控制臺輸出: 外界:newVal = 87 ; oldVal = 88

在控制臺下繼續執行 data.age -= 1,則會輸出 外界:newVal = 86 ; oldVal = 87。

附上一張 Data、defineReactive、dependList、Watcher和外界的關系圖。

淺析vue偵測數據的變化之基本實現

首先通過 defineReactive() 方法將 data 轉為響應式(defineReactive(data, ’age’, ’88’))。

外界通過 Watcher 讀取數據(let value = this.data[this.key]),數據的 getter 則會被觸發,于是通過 globalData 收集Watcher。

當數據被修改(data.age -= 1), 會觸發 setter,會通知依賴(dependList),依賴則會通知 Watcher(w.update(newVal, val)),最后 Watcher 再通知給外界。

二、關于 Object 的問題

思考一下:上面的例子,繼續執行 delete data.age 會通知到外界嗎?

不會。因為不會觸發 setter。請接著看:

<!DOCTYPE html><html lang='en'><head> <meta charset='UTF-8'> <meta name='viewport' content='width=device-width, initial-scale=1.0'> <title>Document</title> <script src='https://cdn.jsdelivr.net/npm/vue/dist/vue.js'></script></head><body> <div id=’app’><section> {{ p1.name }} {{ p1.age }}</section> </div><script>const app = new Vue({ el: ’#app’, data: {p1: { name: ’ph’, age: 18} }})</script></body></html>

運行后,頁面會顯示 ph 18。我們知道更改數據,視圖會重新渲染,于是在控制臺執行 delete app.p1.name,發現頁面沒有變化。這與上面示例中執行 delete data.age 一樣,都不會觸發setter,也就不會通知到外界。

為了解決這個問題,Vue提供了兩個 API(稍后將介紹它們):vm.$set 和 vm.$delete。

如果你繼續執行 app.$delete(app.p1, ’age’),你會發現頁面沒有任何信息了(name 屬性已經用 delete 刪除了,只是當時沒有重新渲染而已)。

注:如果這里執行 app.p1.sex = ’man’,用到數據 p1 的地方也不會被通知到,這個問題可以通過 vm.$set 解決。

三、Array 的變化偵測3.1、背景

假如數據是 let data = {a:1, b:[11, 22]},通過 Object.defineProperty 將其轉為響應式之后,我們修改數據 data.a = 2,會通知到外界,這個好理解;同理 data.b = [11, 22, 33] 也會通知到外界,但如果換一種方式修改數據 b,就像這樣 data.b.push(33),是不會通知到外界的,因為沒走 setter。請看示例:

function defineReactive(obj, key, val) { Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function () {console.log(`get val = ${val}`)return val }, set: function reactiveSetter (newVal) {if(val === newVal){ return}console.log(`set val = ${newVal}; oldVal = ${val}`)val = newVal } });}// 以下是測試代碼 {1}let data = {}defineReactive(data, ’a’, [11,22])data.a.push(33) // get val = 11,22 (沒有觸發 setter) {2} data.a // get val = 11,22,33 data.a = 1 // set val = 1; oldVal = 11,22,33(觸發 setter)

通過 push() 方法改變數組的值,確實沒有觸發 setter(行{2}),也就不能通知外界。這里好像說明了一個問題:通過 Object.definePropery() 方法,只能將對象轉為響應式,不能將數組轉為響應式。

其實 Object.definePropery() 可以將數組轉為響應式。請看示例:

// 繼續上面的例子,將測試代碼(行{1})改為:let data = []defineReactive(data, ’0’, 11)data[0] = 22 // set val = 22; oldVal = 11data.push(33) // 不會觸發 {10}

雖然 Object.definePropery() 可以將數組轉為響應式,但通過 data.push(33)(行{10})這種方式修改數組,仍然不會通知到外界。

所以在 Vue 中,將數據轉為響應式,用了兩套方式:對象使用 Object.defineProperty();數組則使用另一套。

3.2、實現

es6 中可以用 Proxy 偵測數組的變化。請看示例:

let data = [11,22]let p = new Proxy(data, { set: function(target, prop, value, receiver) {target[prop] = value;console.log(’property set: ’ + prop + ’ = ’ + value);return true; } })console.log(p)p.push(33)/*輸出:[ 11, 22 ]property set: 2 = 33property set: length = 3*/

es6 以前就稍微麻煩點,可以使用攔截器。原理是:當我們執行 [].push() 時會調用數組原型(Array.prototype)中的方法。我們在 [].push() 和 Array.prototype 之間增加一個攔截器,以后調用 [].push() 時先執行攔截器中的 push() 方法,攔截器中的 push() 在調用 Array.prototype 中的 push() 方法。請看示例:

// 數組原型let arrayPrototype = Array.prototype// 創建攔截器let interceptor = Object.create(arrayPrototype)// 將攔截器與原始數組的方法關聯起來;(’push,pop,unshift,shift,splice,sort,reverse’).split(’,’).forEach(method => { let origin = arrayPrototype[method]; Object.defineProperty(interceptor, method, {value: function(...args){ console.log(`攔截器: args = ${args}`) return origin.apply(this, args);},enumerable: false,writable: true,configurable: true })});// 測試let arr1 = [’a’]let arr2 = [10]arr1.push(’b’)// 偵測數組 arr2 的變化Object.setPrototypeOf(arr2, interceptor) // {20}arr2.push(11) // 攔截器: args = 11arr2.unshift(22) // 攔截器: args = 22

這個例子將能改變數組自身內容的 7 個方法都加入到了攔截器。如果需要偵測哪個數組的變化,就將該數組的原型指向攔截器(行{20})。當我們通過 push 等 7 個方法修改該數組時,則會在攔截器中觸發,從而可以通知外界。

到這里,我們只完成了偵測數組變化的任務。

數據變化,通知到外界。上文編碼的實現只是針對 Object 數據,而這里需要針對 Array 數據。

我們也來思考一下同樣的問題:

1.如何偵測數組的變化?

攔截器

2.當數據發生變化的時候,我們通知誰?

Watcher

3.依賴誰?

Watcher

4.何時通知?

修改數據的時候。攔截器中通知。

5.何時收集依賴?

因為要通知用數據的地方。用數據就得讀數據。在讀數據的時候收集。這和對象收集依賴是一樣的。 {a: [11,22]} 比如我們要使用 a 數組,肯定得訪問對象的屬性 a。

6.收集到哪里?

對象是在每個屬性中收集依賴,但這里得考慮數組在攔截器中能觸發依賴,位置可能得調整

就到這里,不在繼續展開了。接下來的文章中,我會將 vue 中與數據偵測相關的源碼摘出來,配合本文,簡單分析一下。

四、關于 Array 的問題

// 需要自己引入 vue.js。后續也盡可能只羅列核心代碼<div id=’app’><section> {{ p1[0] }} {{ p1[1] }}</section></div><script>const app = new Vue({ el: ’#app’, data: {p1: [’ph’, ’18’] }})</script>

運行后在頁面顯示 ph 18,控制臺執行 app.p1[0] = ’lj’ 頁面沒反應,因為數組只有調用指定的 7 個方法才能通過攔截器通知外界。如果執行 app.$set(app.p1, 0, ’pm’) 頁面內容會變成 pm 18。

以上就是淺析vue偵測數據的變化之基本實現的詳細內容,更多關于vue偵測數據的變化的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
噜噜噜在线观看免费视频日韩 | 日韩视频精品在线观看| 欧美韩国日本不卡| 欧美成人一品| 欧美精品一区二区三区在线看午夜 | 久久久国际精品| 国产自产在线视频一区| 国产精品久久久久久久久免费相片| 欧美精品激情| 午夜视频久久久久久| 色吧成人激情小说| 99久久精品免费看| 国产日本欧洲亚洲| 一本色道久久综合亚洲精品不卡| 亚洲欧美日韩在线播放| 一本到高清视频免费精品| 国产精品一二二区| 国产精品乱人伦中文| 国产日韩欧美一区二区三区在线观看| 一区二区三区在线免费视频| 日韩欧美国产一区二区三区| 在线视频观看日韩| 蜜臀国产一区二区三区在线播放 | 色综合久久88色综合天天免费| 日本在线不卡视频| 中文字幕一区二区视频| 久久er精品视频| 欧美人与性动xxxx| 尤物网精品视频| 黑人巨大精品欧美黑白配亚洲| 欧美经典一区二区| 91精品麻豆日日躁夜夜躁| 99精品国产高清一区二区| 色综合色狠狠天天综合色| 国产在线精品一区二区不卡了| 亚洲人成网站影音先锋播放| 久久精品免视看| 在线一区二区三区| 久久另类ts人妖一区二区| 亚洲精品1区2区| 亚洲欧美日韩国产| 欧美一区二区三区四区夜夜大片| 国产精品亚洲人在线观看| 日本视频一区二区三区| 日本怡春院一区二区| 久久成人麻豆午夜电影| 加勒比av一区二区| 国产一区三区三区| 狠狠v欧美v日韩v亚洲ⅴ| 蜜桃视频在线一区| 粉嫩aⅴ一区二区三区四区五区| 亚洲综合一区在线| 裸体健美xxxx欧美裸体表演| 久久精品国产精品亚洲红杏| 国产成人一区在线| 99久久99久久精品国产片果冻| 亚洲亚洲人成综合网络| 亚洲欧美二区三区| 精品一区二区三区的国产在线播放| 精品一区二区三区日韩| 91丨九色porny丨蝌蚪| 性色av一区二区怡红| 日本韩国欧美在线| 精品国内二区三区| 亚洲观看高清完整版在线观看| 激情久久五月天| 狠狠88综合久久久久综合网| 激情成人亚洲| 精品国产凹凸成av人网站| 亚洲一级二级在线| 全部av―极品视觉盛宴亚洲| 久久精品国产亚洲5555| 午夜精品一区二区三区四区 | 国产乱码精品| 欧美酷刑日本凌虐凌虐| 亚洲欧洲日韩一区二区三区| 国产真实乱对白精彩久久| 国产精品久久7| 国产精品情趣视频| 蜜臀av一级做a爰片久久| 午夜不卡在线视频| 不卡一区二区在线| 欧美日韩在线三级| 久久一日本道色综合久久| 国产精品入口66mio| 国产精品美女一区二区三区 | 国产精品vip| 日韩高清不卡在线| 福利一区二区在线| aaa欧美日韩| 日本精品视频一区二区| 亚洲三级电影全部在线观看高清| 蜜臀国产一区二区三区在线播放| 99精品欧美一区| 国产精品入口66mio| 7777精品伊人久久久大香线蕉完整版| 久久网站热最新地址| 亚洲自拍都市欧美小说| 99久久精品久久久久久清纯| 在线视频欧美精品| 亚洲三级久久久| 北条麻妃一区二区三区| 亚洲在线观看| 国产精品久久久久久久久免费丝袜| 亚洲一区二区三区四区的| 国产一区二区三区久久久| 亚洲在线播放| 日本道免费精品一区二区三区| 日本一区二区三区高清不卡| 99精品黄色片免费大全| 欧美高清性hdvideosex| 久久国产婷婷国产香蕉| 午夜精品福利视频网站| 性8sex亚洲区入口| 依依成人综合视频| 精品一区二区久久| 欧美日韩精品高清| 日韩黄色一级片| 欧美日韩aaa| 国产v综合v亚洲欧| 国产亚洲综合色| 欧美bbbxxxxx| 性做久久久久久免费观看 | 国产精品一区2区| 日韩欧美电影在线| 在线观看一区欧美| 亚洲成年人影院| 美女91精品| 男女男精品视频| 亚洲一区二区三区涩| 蜜桃视频第一区免费观看| 欧美伦理电影网| 好看不卡的中文字幕| 成人av电影在线观看| 欧美国产精品专区| 久久久国产亚洲精品| 国产精品99久久久久久似苏梦涵 | 欧美韩国日本一区| 亚洲三级在线观看| 亚洲欧洲日产国码二区| 欧美日韩电影在线播放| 亚洲免费播放| 99视频热这里只有精品免费| 亚洲黄色录像片| 性8sex亚洲区入口| 国产乱子轮精品视频| 国产欧美日本一区二区三区| 欧美猛男gaygay网站| 国产91综合一区在线观看| 亚洲精品一区二区精华| 精品一区二区影视| 在线观看国产精品网站| 韩国免费一区| 99久久国产综合精品女不卡| av在线不卡免费看| 国产一区二区在线看| 五月天中文字幕一区二区| 亚洲欧洲综合另类在线| 91网上在线视频| 日韩一级片网址| 国产欧美不卡| 中文精品视频| 色综合天天综合在线视频| 丁香天五香天堂综合| 成人精品一区二区三区四区| 麻豆91精品91久久久的内涵| 亚洲欧美日韩久久| 亚洲精品国产高清久久伦理二区| 免费在线观看一区| 日本欧美加勒比视频| 秋霞电影网一区二区| 国产jizzjizz一区二区| 日本在线不卡一区| 国产乱码精品一区二区三区av| 亚洲视频免费看| 日韩精品一级二级| 国产激情一区二区三区| 国产成人精品免费在线| www.综合网.com| 亚洲bt欧美bt精品| 国产精品一二一区| 国产91对白在线观看九色| 97se亚洲国产综合自在线观| 国产亚洲精品久久飘花| 老妇喷水一区二区三区| 91精品国产欧美一区二区成人| 这里只有精品视频在线观看| 欧美精品一区二区三区蜜桃视频| 美女成人午夜| 久久综合色之久久综合| 精品粉嫩aⅴ一区二区三区四区| 国产亚洲综合精品| 亚洲人成伊人成综合网小说| 日韩avvvv在线播放| 欧美一区1区三区3区公司| 不卡在线观看av| 亚洲人体大胆视频| 午夜宅男久久久| 亚洲乱码日产精品bd| 成人免费不卡视频|