摘要:定義是一個計(jì)算屬性類似于過濾器對綁定到的數(shù)據(jù)進(jìn)行處理用法不可在里面定義如果定義會報如下圖片的錯誤因?yàn)閷?yīng)的作為計(jì)算屬性定義并返回對應(yīng)的結(jié)果給這個變量變量不可被重復(fù)定義和賦值和用法回調(diào)函數(shù)當(dāng)需要讀取當(dāng)前屬性值是執(zhí)行,根據(jù)相關(guān)數(shù)據(jù)計(jì)算并返回當(dāng)前
1.computed 1.1 定義
是一個計(jì)算屬性,類似于過濾器,對綁定到view的數(shù)據(jù)進(jìn)行處理
1.2 get用法data: { firstName: "Foo", lastName: "Bar" }, computed: { fullName: function () { return this.firstName + " " + this.lastName } }
fullName不可在data里面定義,
如果定義會報如下圖片的錯誤,因?yàn)閷?yīng)的computed作為計(jì)算屬性定義fullName并返回對應(yīng)的結(jié)果給這個變量,變量不可被重復(fù)定義和賦值
data: { firstName: "Foo", lastName: "Bar" }, computed: { fullName:{ get(){//回調(diào)函數(shù) 當(dāng)需要讀取當(dāng)前屬性值是執(zhí)行,根據(jù)相關(guān)數(shù)據(jù)計(jì)算并返回當(dāng)前屬性的值 return this.firstName + " " + this.lastName }, set(val){//監(jiān)視當(dāng)前屬性值的變化,當(dāng)屬性值發(fā)生變化時執(zhí)行,更新相關(guān)的屬性數(shù)據(jù) //val就是fullName的最新屬性值 console.log(val) const names = val.split(" "); console.log(names) this.firstName = names[0]; this.lastName = names[1]; } } }2. watch 2.1 定義
watch是一個觀察的動作
2.2 示例data: { firstName: "Foo", lastName: "Bar", fullName: "Foo Bar" }, watch: { firstName: function (val) { this.fullName = val + " " + this.lastName }, lastName: function (val) { this.fullName = this.firstName + " " + val } }
上面是監(jiān)聽firstName和lastName的變化,但是僅限簡單數(shù)據(jù)類型
2.2 監(jiān)聽簡單數(shù)據(jù)類型data(){ return{ "first":2 } }, watch:{ first(){ console.log(this.first) } },2.3 監(jiān)聽復(fù)雜數(shù)據(jù)類型
1.監(jiān)聽復(fù)雜數(shù)據(jù)類型需用深度監(jiān)聽
data(){ return{ "first":{ second:0 } } }, watch:{ secondChange:{ handler(oldVal,newVal){ console.log(oldVal) console.log(newVal) }, deep:true } },
2.console.log打印的結(jié)果,發(fā)現(xiàn)oldVal和newVal值是一樣的,所以深度監(jiān)聽雖然可以監(jiān)聽到對象的變化,但是無法監(jiān)聽到具體對象里面那個屬性的變化
3.oldVal和newVal值一樣的原因是它們索引同一個對象/數(shù)組。Vue 不會保留修改之前值的副本
vm.$watch的深度監(jiān)聽
4.深度監(jiān)聽對應(yīng)的函數(shù)名必須為handler,否則無效果,因?yàn)閣atcher里面對應(yīng)的是對handler的調(diào)用
2.4 監(jiān)聽對象單個屬性方法一:可以直接對用對象.屬性的方法拿到屬性 data(){ return{ "first":{ second:0 } } }, watch:{ first.second:function(newVal,oldVal){ console.log(newVal,oldVal); } },
方法二:watch如果想要監(jiān)聽對象的單個屬性的變化,必須用computed作為中間件轉(zhuǎn)化,因?yàn)閏omputed可以取到對應(yīng)的屬性值
data(){ return{ "first":{ second:0 } } }, computed:{ secondChange(){ return this.first.second } }, watch:{ secondChange(){ console.log("second屬性值變化了") } },3 computed和watch的區(qū)別 3.1 computed特性
1.是計(jì)算值,
2.應(yīng)用:就是簡化tempalte里面{{}}計(jì)算和處理props或$emit的傳值
3.具有緩存性,頁面重新渲染值不變化,計(jì)算屬性會立即返回之前的計(jì)算結(jié)果,而不必再次執(zhí)行函數(shù)
1.是觀察的動作,
2.應(yīng)用:監(jiān)聽props,$emit或本組件的值執(zhí)行異步操作
3.無緩存性,頁面重新渲染時值不變化也會執(zhí)行
傳入的值想作為局部變量來使用,直接使用會
props:["listShop"], data(){ return{} }, created(){ this.listShop=30 }
報錯
這個錯誤是說的避免直接修改父組件傳入的值,因?yàn)闀淖兏附M件的值,貼上官網(wǎng)介紹
3.2 解決方案1簡單數(shù)據(jù)類型解決方案:
所以可以在data中重新定義一個變量,改變指向,但是也只是針對簡單數(shù)據(jù)類型,因?yàn)閺?fù)雜數(shù)據(jù)類型棧存貯的是指針,
props:["listShop"], data(){ return{ listShopChild:this.listShop } }, created(){ this.listShopChild=30 }
這樣就可以愉快的更改傳入的簡單數(shù)據(jù)類型的數(shù)據(jù)啦!不會有任何報錯,也不會影響父組件!
3.4 存在的問題復(fù)雜數(shù)據(jù)類型在棧中存貯的是指針,所以賦值給新的變量也會改變原始的變量值.那么應(yīng)該咋整呢?
1.可以手動深度克隆一個復(fù)雜的數(shù)據(jù)出來,循環(huán)或者遞歸都行
數(shù)組深度克隆:
var x = [1,2,3]; var y = []; for (var i = 0; i < x.length; i++) { y[i]=x[i]; } console.log(y); //[1,2,3] y.push(4); console.log(y); //[1,2,3,4] console.log(x); //[1,2,3]
對象深度克隆:
var x = {a:1,b:2}; var y = {}; for(var i in x){ y[i] = x[i]; } console.log(y); //Object {a: 1, b: 2} y.c = 3; console.log(y); //Object {a: 1, b: 2, c: 3} console.log(x); //Object {a: 1, b: 2}
函數(shù)深度克隆
var x = function(){console.log(1);}; var y = x; y = function(){console.log(2);}; x(); //1 y(); //2
為什么函數(shù)可以直接賦值克隆?
由于函數(shù)對象克隆之后的對象會多帶帶復(fù)制一次并存儲實(shí)際數(shù)據(jù),因此并不會影響克隆之前的對象。所以采用簡單的復(fù)制“=”即可完成克隆。
2.Object.assign
只會對只是一級屬性復(fù)制,比淺拷貝多深拷貝了一層而已,所以還是無法達(dá)到深度克隆的目的.
詳請請戳
3.強(qiáng)大的JSON.stringify和JSON.parse
const obj1 = JSON.parse(JSON.stringify(obj));
這是ES5新出來的API,先將對象轉(zhuǎn)化為字符串,就是簡單數(shù)據(jù)類型賦值,再用JSON.parse轉(zhuǎn)化
3.5 解決方案2直接用computed改變
computed:{ listShopChild(){ return this.listShop } }3.5 存在的問題
注意:此時用computed時,如果是數(shù)組this.$set(arr,1,true)對應(yīng)的值耶不更新,
這個很坑,這個bug我找個很久
如果傳入的值只是在data定義,并未在methods或生命周期鉤子更改,直接改變也會報錯
所以還是可以先用局部變量接收,再修改,這個坑比較多
監(jiān)聽本組件計(jì)算和監(jiān)聽
4.2 應(yīng)用2計(jì)算或監(jiān)聽父傳子的props值
4.3 應(yīng)用3分為簡單數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型監(jiān)聽,監(jiān)聽方法如上watch的使用
4.4 應(yīng)用4監(jiān)聽vuex的state或者getters值的變化
computed:{ stateDemo(){ return this.$store.state.demoState; } } watch:{ stateDemo(){ console.log("vuex變化啦") } }5. computed和watch的原理分析
很開心小伙伴們能看到這里,接下來給大家簡單羅列下他們的原理!
5.1 computed的原理深入理解 Vue Computed 計(jì)算屬性
5.2 watch的原理分為三個過程:實(shí)例化Vue、調(diào)用$watch方法、屬性變化,觸發(fā)回調(diào)
Vue的數(shù)據(jù)依賴實(shí)現(xiàn)原理簡析
vue中$watch源碼閱讀筆記
公共類
function defineReactive(data, key, val, fn) { let subs = [] // 新增 Object.defineProperty(data, key, { configurable: true, enumerable: true, get: function() { // 新增 if (data.$target) { subs.push(data.$target) } return val }, set: function(newVal) { if (newVal === val) return fn && fn(newVal) // 新增 if (subs.length) { // 用 setTimeout 因?yàn)榇藭r this.data 還沒更新 setTimeout(() => { subs.forEach(sub => sub()) }, 0) } val = newVal }, }) }6.1 computed實(shí)現(xiàn)
function computed(ctx, obj) { let keys = Object.keys(obj) let dataKeys = Object.keys(ctx.data) dataKeys.forEach(dataKey => { defineReactive(ctx.data, dataKey, ctx.data[dataKey]) }) let firstComputedObj = keys.reduce((prev, next) => { ctx.data.$target = function() { ctx.setData({ [next]: obj[next].call(ctx) }) } prev[next] = obj[next].call(ctx) ctx.data.$target = null return prev }, {}) ctx.setData(firstComputedObj) }6.1 watch實(shí)現(xiàn)
function watch(ctx, obj) { Object.keys(obj).forEach(key => { defineReactive(ctx.data, key, ctx.data[key], function(value) { obj[key].call(ctx, value) }) }) }
https://segmentfault.com/a/11...
大家如果發(fā)現(xiàn)有什么錯誤,歡迎指正,共同交流。如果覺得篇文章真的對你有點(diǎn)作用。
謝謝親們能看完!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/51721.html
摘要:定義是一個計(jì)算屬性類似于過濾器對綁定到的數(shù)據(jù)進(jìn)行處理用法不可在里面定義如果定義會報如下圖片的錯誤因?yàn)閷?yīng)的作為計(jì)算屬性定義并返回對應(yīng)的結(jié)果給這個變量變量不可被重復(fù)定義和賦值和用法回調(diào)函數(shù)當(dāng)需要讀取當(dāng)前屬性值是執(zhí)行,根據(jù)相關(guān)數(shù)據(jù)計(jì)算并返回當(dāng)前 1.computed 1.1 定義 是一個計(jì)算屬性,類似于過濾器,對綁定到view的數(shù)據(jù)進(jìn)行處理 1.2 get用法 data: { ...
摘要:當(dāng)某個屬性發(fā)生變化,觸發(fā)攔截函數(shù),然后調(diào)用自身消息訂閱器的方法,遍歷當(dāng)前中保存著所有訂閱者的數(shù)組,并逐個調(diào)用的方法,完成響應(yīng)更新。 編者按:我們會不時邀請工程師談?wù)動幸馑嫉募夹g(shù)細(xì)節(jié),希望知其所以然能讓大家在面試有更出色表現(xiàn)。也給面試官提供更多思路。 showImg(https://segmentfault.com/img/bVbgYyU?w=1200&h=600); 雖然目前的技術(shù)...
摘要:源碼對于計(jì)算屬性的理解這是我最近學(xué)習(xí)源碼的一個個人總結(jié)和理解,所以可能并不適合每一位讀者本文的整體脈絡(luò)如下,首先盡可能去掉細(xì)節(jié),對計(jì)算屬性源碼的大致實(shí)現(xiàn)有一個了解,然后舉一例子,分別談?wù)動?jì)算屬性依賴收集和派發(fā)更新的流程。 vue源碼-對于「計(jì)算屬性」的理解 這是我最近學(xué)習(xí)vue源碼的一個個人總結(jié)和理解,所以可能并不適合每一位讀者 本文的整體脈絡(luò)如下,首先盡可能去掉細(xì)節(jié),對計(jì)算屬性源碼的...
摘要:當(dāng)一個組件沒有聲明任何時,這里會包含所有父作用域的綁定和除外,并且可以通過傳入內(nèi)部組件在創(chuàng)建高級別的組件時非常有用。 寫在前面 組件間的通信是是實(shí)際開發(fā)中非常常用的一環(huán),如何使用對項(xiàng)目整體設(shè)計(jì)、開發(fā)、規(guī)范都有很實(shí)際的的作用,我在項(xiàng)目開發(fā)中對此深有體會,總結(jié)下vue組件間通信的幾種方式,討論下各自的使用場景 文章對相關(guān)場景預(yù)覽 父->子組件間的數(shù)據(jù)傳遞 子->父組件間的數(shù)據(jù)傳遞 兄弟...
摘要:知識點(diǎn)閉包問題執(zhí)行機(jī)制定時器線程理解構(gòu)造函數(shù)內(nèi)的方法與構(gòu)造函數(shù)屬性上方法的對比中都經(jīng)歷了什么深入理解中的屬性和特性中的方法詳解為什么編程語言的都要定義數(shù)據(jù)類型中與的區(qū)別輕松理解基本包裝對象中數(shù)據(jù)類型內(nèi)置對象包裝類型對象關(guān)系基礎(chǔ)之?dāng)?shù)組中的邏輯 JS知識點(diǎn) JS hoist JS閉包問題 JS執(zhí)行機(jī)制 JS定時器線程理解 構(gòu)造函數(shù)內(nèi)的方法與構(gòu)造函數(shù)prototype屬性上方法的對比 JS...
閱讀 3776·2023-04-25 20:00
閱讀 3121·2021-09-22 15:09
閱讀 518·2021-08-25 09:40
閱讀 3425·2021-07-26 23:38
閱讀 2214·2019-08-30 15:53
閱讀 1102·2019-08-30 13:46
閱讀 2799·2019-08-29 16:44
閱讀 2054·2019-08-29 15:32