摘要:定義是一個計算屬性類似于過濾器對綁定到的數(shù)據(jù)進行處理用法不可在里面定義如果定義會報如下圖片的錯誤因為對應的作為計算屬性定義并返回對應的結果給這個變量變量不可被重復定義和賦值和用法回調(diào)函數(shù)當需要讀取當前屬性值是執(zhí)行,根據(jù)相關數(shù)據(jù)計算并返回當前
1.computed 1.1 定義
是一個計算屬性,類似于過濾器,對綁定到view的數(shù)據(jù)進行處理
1.2 get用法data: { firstName: "Foo", lastName: "Bar" }, computed: { fullName: function () { return this.firstName + " " + this.lastName } }
fullName不可在data里面定義,
如果定義會報如下圖片的錯誤,因為對應的computed作為計算屬性定義fullName并返回對應的結果給這個變量,變量不可被重復定義和賦值
data: { firstName: "Foo", lastName: "Bar" }, computed: { fullName:{ get(){//回調(diào)函數(shù) 當需要讀取當前屬性值是執(zhí)行,根據(jù)相關數(shù)據(jù)計算并返回當前屬性的值 return this.firstName + " " + this.lastName }, set(val){//監(jiān)視當前屬性值的變化,當屬性值發(fā)生變化時執(zhí)行,更新相關的屬性數(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)聽復雜數(shù)據(jù)類型
1.監(jiān)聽復雜數(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打印的結果,發(fā)現(xiàn)oldVal和newVal值是一樣的,所以深度監(jiān)聽雖然可以監(jiān)聽到對象的變化,但是無法監(jiān)聽到具體對象里面那個屬性的變化
3.oldVal和newVal值一樣的原因是它們索引同一個對象/數(shù)組。Vue 不會保留修改之前值的副本
vm.$watch的深度監(jiān)聽
4.深度監(jiān)聽對應的函數(shù)名必須為handler,否則無效果,因為watcher里面對應的是對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作為中間件轉化,因為computed可以取到對應的屬性值
data(){ return{ "first":{ second:0 } } }, computed:{ secondChange(){ return this.first.second } }, watch:{ secondChange(){ console.log("second屬性值變化了") } },3 computed和watch的區(qū)別 3.1 computed特性
1.是計算值,
2.應用:就是簡化tempalte里面{{}}計算和處理props或$emit的傳值
3.具有緩存性,頁面重新渲染值不變化,計算屬性會立即返回之前的計算結果,而不必再次執(zhí)行函數(shù)
1.是觀察的動作,
2.應用:監(jiān)聽props,$emit或本組件的值執(zhí)行異步操作
3.無緩存性,頁面重新渲染時值不變化也會執(zhí)行
傳入的值想作為局部變量來使用,直接使用會
props:["listShop"], data(){ return{} }, created(){ this.listShop=30 }
報錯
這個錯誤是說的避免直接修改父組件傳入的值,因為會改變父組件的值,貼上官網(wǎng)介紹
3.2 解決方案1簡單數(shù)據(jù)類型解決方案:
所以可以在data中重新定義一個變量,改變指向,但是也只是針對簡單數(shù)據(jù)類型,因為復雜數(shù)據(jù)類型棧存貯的是指針,
props:["listShop"], data(){ return{ listShopChild:this.listShop } }, created(){ this.listShopChild=30 }
這樣就可以愉快的更改傳入的簡單數(shù)據(jù)類型的數(shù)據(jù)啦!不會有任何報錯,也不會影響父組件!
3.4 存在的問題復雜數(shù)據(jù)類型在棧中存貯的是指針,所以賦值給新的變量也會改變原始的變量值.那么應該咋整呢?
1.可以手動深度克隆一個復雜的數(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ù)對象克隆之后的對象會多帶帶復制一次并存儲實際數(shù)據(jù),因此并不會影響克隆之前的對象。所以采用簡單的復制“=”即可完成克隆。
2.Object.assign
只會對只是一級屬性復制,比淺拷貝多深拷貝了一層而已,所以還是無法達到深度克隆的目的.
詳請請戳
3.強大的JSON.stringify和JSON.parse
const obj1 = JSON.parse(JSON.stringify(obj));
這是ES5新出來的API,先將對象轉化為字符串,就是簡單數(shù)據(jù)類型賦值,再用JSON.parse轉化
3.5 解決方案2直接用computed改變
computed:{ listShopChild(){ return this.listShop } }3.5 存在的問題
注意:此時用computed時,如果是數(shù)組this.$set(arr,1,true)對應的值耶不更新,
這個很坑,這個bug我找個很久
如果傳入的值只是在data定義,并未在methods或生命周期鉤子更改,直接改變也會報錯
所以還是可以先用局部變量接收,再修改,這個坑比較多
監(jiān)聽本組件計算和監(jiān)聽
4.2 應用2計算或監(jiān)聽父傳子的props值
4.3 應用3分為簡單數(shù)據(jù)類型和復雜數(shù)據(jù)類型監(jiān)聽,監(jiān)聽方法如上watch的使用
4.4 應用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 計算屬性
5.2 watch的原理分為三個過程:實例化Vue、調(diào)用$watch方法、屬性變化,觸發(fā)回調(diào)
Vue的數(shù)據(jù)依賴實現(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 因為此時 this.data 還沒更新 setTimeout(() => { subs.forEach(sub => sub()) }, 0) } val = newVal }, }) }6.1 computed實現(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實現(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)有什么錯誤,歡迎指正,共同交流。如果覺得篇文章真的對你有點作用。
謝謝親們能看完!
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92688.html
摘要:定義是一個計算屬性類似于過濾器對綁定到的數(shù)據(jù)進行處理用法不可在里面定義如果定義會報如下圖片的錯誤因為對應的作為計算屬性定義并返回對應的結果給這個變量變量不可被重復定義和賦值和用法回調(diào)函數(shù)當需要讀取當前屬性值是執(zhí)行,根據(jù)相關數(shù)據(jù)計算并返回當前 1.computed 1.1 定義 是一個計算屬性,類似于過濾器,對綁定到view的數(shù)據(jù)進行處理 1.2 get用法 data: { ...
摘要:當某個屬性發(fā)生變化,觸發(fā)攔截函數(shù),然后調(diào)用自身消息訂閱器的方法,遍歷當前中保存著所有訂閱者的數(shù)組,并逐個調(diào)用的方法,完成響應更新。 編者按:我們會不時邀請工程師談談有意思的技術細節(jié),希望知其所以然能讓大家在面試有更出色表現(xiàn)。也給面試官提供更多思路。 showImg(https://segmentfault.com/img/bVbgYyU?w=1200&h=600); 雖然目前的技術...
摘要:源碼對于計算屬性的理解這是我最近學習源碼的一個個人總結和理解,所以可能并不適合每一位讀者本文的整體脈絡如下,首先盡可能去掉細節(jié),對計算屬性源碼的大致實現(xiàn)有一個了解,然后舉一例子,分別談談計算屬性依賴收集和派發(fā)更新的流程。 vue源碼-對于「計算屬性」的理解 這是我最近學習vue源碼的一個個人總結和理解,所以可能并不適合每一位讀者 本文的整體脈絡如下,首先盡可能去掉細節(jié),對計算屬性源碼的...
摘要:當一個組件沒有聲明任何時,這里會包含所有父作用域的綁定和除外,并且可以通過傳入內(nèi)部組件在創(chuàng)建高級別的組件時非常有用。 寫在前面 組件間的通信是是實際開發(fā)中非常常用的一環(huán),如何使用對項目整體設計、開發(fā)、規(guī)范都有很實際的的作用,我在項目開發(fā)中對此深有體會,總結下vue組件間通信的幾種方式,討論下各自的使用場景 文章對相關場景預覽 父->子組件間的數(shù)據(jù)傳遞 子->父組件間的數(shù)據(jù)傳遞 兄弟...
摘要:知識點閉包問題執(zhí)行機制定時器線程理解構造函數(shù)內(nèi)的方法與構造函數(shù)屬性上方法的對比中都經(jīng)歷了什么深入理解中的屬性和特性中的方法詳解為什么編程語言的都要定義數(shù)據(jù)類型中與的區(qū)別輕松理解基本包裝對象中數(shù)據(jù)類型內(nèi)置對象包裝類型對象關系基礎之數(shù)組中的邏輯 JS知識點 JS hoist JS閉包問題 JS執(zhí)行機制 JS定時器線程理解 構造函數(shù)內(nèi)的方法與構造函數(shù)prototype屬性上方法的對比 JS...
閱讀 591·2021-11-15 11:38
閱讀 1174·2021-10-11 10:59
閱讀 3491·2021-09-07 09:58
閱讀 479·2019-08-30 15:44
閱讀 3518·2019-08-28 18:14
閱讀 2599·2019-08-26 13:32
閱讀 3514·2019-08-26 12:23
閱讀 2413·2019-08-26 10:59