日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

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

Vue中避免濫用this去讀取data中數據

瀏覽:24日期:2022-10-04 13:47:59
前言

在Vue中,data選項是個好東西,把數據往里一丟,在一個Vue組件中任何一個地方都可以通過this來讀取data中數據。但是要避免濫用this去讀取data中數據,至于在哪里要避免濫用,如果濫用會導致什么后果,本專欄將會一一揭曉。

一、用this讀取data中數據的過程

在Vue源碼中會把data中數據添加getter函數和setter函數,將其轉成響應式的。getter函數代碼如下所示:

function reactiveGetter() { var value = getter ? getter.call(obj) : val; if (Dep.target) { dep.depend(); if (childOb) { childOb.dep.depend(); if (Array.isArray(value)) { dependArray(value); } } } return value}

用this讀取data中數據時,會觸發getter函數,在其中通過 var value = getter ? getter.call(obj) : val; 獲取到值后執行 return value,實現讀取數據的目的。

這里可以得出一個結論,在Dep.target存在時,使用this去讀取data中數據時會去收集依賴。如果濫用this去讀取data中數據,會多次重復地收集依賴,從而產生性能問題。

二、Dep.target什么時候存在

Dep.target是由依賴賦值的。依賴又稱為Watcher(偵聽者)或者訂閱者。在Vue中有三種依賴,其中兩種是很常見的,就是watch(偵聽器)和computed(計算屬性)。還有一種隱藏的依賴———渲染Watcher,在模板首次渲染的過程中創建的。

Dep.target是在依賴創建時被賦值,依賴是用構造函數Watcher創建。

function Watcher(vm, expOrFn, cb, options, isRenderWatcher) { //... if (typeof expOrFn === ’function’) { this.getter = expOrFn; } else { this.getter = parsePath(expOrFn); } this.value = this.lazy ? undefined : this.get();};Watcher.prototype.get = function get() { pushTarget(this); try { value = this.getter.call(vm, vm); } catch (e) { } return value};Dep.target = null;var targetStack = [];function pushTarget(target) { targetStack.push(target); Dep.target = target;}

在構造函數Watcher最后會執行實例方法get,在實例方法get中執行pushTarget(this)中給Dep.target賦值的。

而依賴是在Vue頁面或組件初次渲染時創建,所以產生的性能問題應該是首次渲染過慢的問題。

三、在何處濫用this去讀取data中數據

在Dep.target存在時去執行這些濫用this去讀取data中數據的代碼會產生性能問題,故還要搞清楚這些代碼是寫在哪里才會被執行到,換句話來說,要搞清楚在哪里濫用this去讀取data中數據會產生性能問題。

在第二小節中介紹了Dep.target被賦值后會執行value = this.getter.call(vm, vm),其中this.getter是一個函數,那么若在其中有用this去讀取data數據,就會去收集依賴,假如濫用的話就會產生性能問題。

this.getter是在創建依賴過程中賦值的,每種依賴的this.getter都是不相同的。下面來一一介紹。

watch(偵聽器)依賴的this.getter是parsePath函數,其函數參數就是偵聽的對象。

var bailRE = new RegExp(('[^' + (unicodeRegExp.source) + '.$_d]'));function parsePath(path) { if (bailRE.test(path)) { return } var segments = path.split(’.’); return function(obj) { for (var i = 0; i < segments.length; i++) { if (!obj) { return } obj = obj[segments[i]]; } return obj }}

如下所示的代碼中的 a 和 a.b.c作為參數傳入parsePath函數會返回一個函數賦值給this.getter,執行this.getter.call(vm, vm)會得到this.a和this.a.b.c的值。在這個過程中不會存在濫用this去讀取data中數據的場景。

watch:{ a:function(newVal, oldVal){ //做點什么 }}vm.$watch(’a.b.c’, function (newVal, oldVal) { // 做點什么}) computed(計算屬性)依賴的this.getter有兩種,如果計算屬性的值是個函數,那么this.getter就是這個函數。如果計算屬性的值是個對象,那么this.getter就是這個對象的get屬性值,get屬性值也是個函數。在這個函數可能會存在濫用this去讀取data中數據的場景,舉個例子,代碼如下所示。

computed:{ d:function(){ let result = 0; for(let key in this.a){ if(this.a[key].num > 20){ result += this.a[key].num + this.b + this.c; }else{ result += this.a[key].num + this.e + this.f; } } return result; }}

在計算屬性d中就存在濫用this去讀取data數據。其中this.a是個數組,此時Dep.target的值為計算屬性d這個依賴,在循環this.a中使用this去獲取中a、b、c、e、f的數據,使這些數據進行一系列復雜的邏輯運算來重復地收集計算屬性d這個依賴。導致獲取計算屬性d的值的速度變慢,從而產生性能問題。

渲染Watcher的this.getter是一個函數如下所示:

updateComponent = function() { vm._update(vm._render(), hydrating);};

其中vm._render()會把template模板生成的渲染函數render轉成虛擬DOM(VNode):vnode = render.call(vm._renderProxy, vm.$createElement);,舉一個例子來說明一下渲染函數render是什么。

例如template模板:

<template> <div class='wrap'> <p>{{a}}<span>{}</span></p> </div></template>

通過vue-loader會生成渲染函數render,如下所示:

(function anonymous() { with(this) { return _c(’div’, { attrs: { 'class': 'wrap' } }, [_c(’p’, [_v(_s(a)), _c(’span’, [_v(_s(b))])])]) }})

其中with語句的作用是為一個或一組語句指定默認對象,例with(this){ a + b } 等同 this.a + this.b,那么在template模板中使用{{ a }}相當使用this去讀取data中的a數據。故在template模板生成的渲染函數render中也可能存在濫用this去讀取data中數據的場景。舉個例子,代碼如下所示:

<template> <div class='wrap'> <div v-for=item in list> <div> {{ arr[item.index][’name’] }} </div> <div> {{ obj[item.id][’age’] }} </div> </div> </div></template>

其中用v-for循環list數組過程中,不斷用this去讀取data中arr、obj的數據,使這些數據進行一系列復雜的邏輯運算來重復收集這個依賴,導致初次渲染的速度變慢,從而產生性能問題。

四、如何避免濫用this去讀取data中數據

綜上所述在計算屬性和template模板中濫用this去讀取data中數據會導致多次重復地收集依賴,從而產生性能問題,那要怎么避免這種情況。

計算屬性中如何避免

用ES6對象解構賦值來避免,計算屬性的值是一個函數,其參數是Vue的實例化this對象,在上述計算屬性中濫用this的例子中可以這樣優化。

優化前:

computed:{ d:function(){ let result = 0; for(let key in this.a){ if(this.a[key].num > 20){ result += this.a[key].num + this.b + this.c; }else{ result += this.a[key].num + this.e + this.f; } } return result; }}

優化后:

computed: { d({ a, b, c, e, f }) { let result = 0; for (let key in a) { if (a[key].num > 20) { result += a[key].num + b + c; } else { result += a[key].num + e + f; } } return result; }}

以上利用解構賦值提前把data數據中的a、b、c、e、f賦值給對應的變量a、b、c、e、f,然后在計算屬性中可以通過這些變量訪問data數據的,且不會觸發data中對應數據的依賴收集。這樣只用this讀取了一次data中的數據,只觸發了一次依賴收集,避免了多次重復地依賴收集產生的性能問題。

template模板中如何避免

提前處理v-for循環所用的數據,不要在v-for循環中去讀取數組、對象類型的數據。在上述template模板中濫用this的例子中可以這樣優化。

假設list、arr、obj皆是服務端返回來的數據,且arr和obj沒有用到任何模塊渲染中,可以這樣優化。

優化前:

<template> <div class='wrap'> <div v-for=item in list> <div> {{ arr[item.index][’name’] }} </div> <div> {{ obj[item.id][’age’] }} </div> </div> </div></template>

優化后:

<template> <div class='wrap'> <div v-for=item in listData> <div{{item.name}} </div> <div>{{item.age}}</div> </div> </div></template><script>const arr = [];const obj = {}export default { data() { return { list: [], } }, computed: { listData: function ({list}) { list.forEach(item => { item.name = arr[item.index].name; item.age = obj[item.id].age; }) return list; } },}</script>

以上就是Vue中避免濫用this去讀取data中數據的詳細內容,更多關于Vue中避免濫用this的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
午夜久久影院| 国产欧美久久一区二区三区| 欧美91在线| 国产精品白丝一区二区三区| 卡一卡二国产精品| 在线精品亚洲欧美日韩国产| av高清一区| 亚洲美洲欧洲综合国产一区| 久久福利精品| 日韩美女国产精品| 麻豆精品久久久| 日韩电影免费网址| 久久高清免费观看| 国产欧美另类| 蜜桃视频在线网站| 美女亚洲一区| 97成人在线| 在线一区av| 少妇精品在线| 成人三级高清视频在线看| 影院欧美亚洲| 国产精品日韩精品中文字幕| 91看片一区| 日本亚州欧洲精品不卡| 色婷婷综合网| 中文字幕亚洲精品乱码| 国产在视频一区二区三区吞精| 久久精品中文| 日韩高清不卡在线| 亚洲www啪成人一区二区| 亚洲一区国产| 亚洲免费一区三区| 日韩av有码| 亚洲精品中文字幕99999| 精品国产精品国产偷麻豆| 激情综合网址| 国产精品久久777777毛茸茸| 九九久久电影| 国产在线视频欧美一区| 热久久久久久久| 亚洲精品成人图区| 日本一区二区三区视频在线看| 欧美gv在线| 国产精品欧美日韩一区| 午夜日本精品| 久久精品伊人| 中文无码久久精品| 色天使综合视频| 国产精品videossex| 99精品99| 黄毛片在线观看| 欧美亚洲tv| 噜噜噜躁狠狠躁狠狠精品视频| 荡女精品导航| 欧美一区久久| 日韩中文字幕区一区有砖一区| 在线人成日本视频| 日韩av影院| 精品中文一区| 国产黄大片在线观看| 日本成人中文字幕| 尤物在线精品| 99久久亚洲精品蜜臀| 久久久久伊人| 久久精品凹凸全集| 亚洲香蕉久久| 亚洲免费网址| 亚洲激情另类| 免费不卡中文字幕在线| 六月婷婷综合| 精品国产18久久久久久二百| 日本a级不卡| 亚洲精品国产精品粉嫩| 国产精品试看| 日韩一区二区免费看| 国产麻豆久久| 亚洲精品在线影院| 日韩欧美另类一区二区| 国产91在线精品| 美女精品久久| 久久99精品久久久久久园产越南| 日韩av电影一区| 日韩欧美中文在线观看| 一本综合精品| 日韩欧美在线精品| 91精品国产自产精品男人的天堂| 蜜桃传媒麻豆第一区在线观看| 午夜欧美理论片| 国产精品美女久久久浪潮软件| 在线综合亚洲| 一本色道精品久久一区二区三区| 伊人久久大香线蕉av不卡| 亚洲91精品| 欧美成人综合| 亚洲一区二区三区免费在线观看| 亚洲少妇诱惑| 亚洲一区二区三区久久久| 中文字幕av亚洲精品一部二部| 天使萌一区二区三区免费观看| 亚洲一区网站| 亚洲一区二区av| 久久精品99国产国产精| 国产精品久久久久久久久久妞妞 | 久久久人人人| 久久网站免费观看| 欧美色图一区| 99视频精品免费观看| 亚洲伊人精品酒店| 18国产精品| 国产精品麻豆久久| 久久精品国语| 一区二区91| 国产精品1区| 在线观看精品| 国产农村妇女精品一区二区| 最近国产精品视频| 日韩欧美在线精品| 精品视频一区二区三区四区五区| 日韩欧美网址| 国产亚洲在线观看| 日韩中出av| 久久只有精品| 国产精品av久久久久久麻豆网| 久久亚洲影院| 麻豆精品视频在线观看| 亚洲播播91| 久久最新视频| 麻豆一区在线| 在线国产一区| 欧美亚洲自偷自偷| 日韩美女一区二区三区在线观看| 亚洲高清激情| 欧美日韩精品一区二区三区视频| 国产aⅴ精品一区二区三区久久| 黄色成人91| 国产精品久久久久久久久久妞妞 | 亚洲一级在线| 国产精品久久久久毛片大屁完整版| 国产一区二区三区不卡av| 欧美不卡在线| 国产日产一区| 欧美特黄一级大片| 国产精品手机在线播放| 精品中文字幕一区二区三区av| 久久国产日韩欧美精品| 婷婷综合六月| 日韩超碰人人爽人人做人人添| 日韩精品诱惑一区?区三区| 美日韩精品视频| 国内精品美女在线观看| 久久福利一区| 国产精品麻豆久久| 日韩国产在线观看一区| 欧美一区久久久| 日韩欧美四区| 亚洲激情五月| 乱一区二区av| 亚洲精品欧美| 欧美亚洲国产激情| 久久久久九九精品影院| 丝袜脚交一区二区| 日本蜜桃在线观看视频| 欧美日韩午夜电影网| 亚洲国产一区二区三区在线播放| 麻豆国产精品777777在线| 欧美一区=区| 亚洲日本网址| 欧美aaaaaa午夜精品| 男人的天堂久久精品| 88xx成人免费观看视频库| 欧美激情三区| 青青草91久久久久久久久| 一区免费在线| 成人免费电影网址| 精品国产精品国产偷麻豆| 日韩精品高清不卡| 日韩一区二区免费看| 999精品色在线播放| 精品一区二区三区免费看 | 亚洲精一区二区三区| 国产91精品对白在线播放| 美女精品视频在线| 日韩精品一级| 99国产精品自拍| 99精品在线观看| 麻豆视频在线看| 精品国产一区二区三区2021| 日本va欧美va精品发布| 老司机精品久久| 狠狠干成人综合网| 欧美sm一区| 日韩精品永久网址| а√天堂8资源中文在线| 麻豆久久久久久| 欧美亚洲网站| 日韩av电影一区| 日韩精品成人在线观看| 亚洲欧美网站| 亚洲免费精品| 欧美日韩免费观看一区=区三区|