摘要

本文主要講述的是犀光科技前端,在開發過程遇到的值的引用問題。

正文

開局一張圖。帶大家直觀的瞭解下普通值和引用值的區別。

在vue裏面父組件向子組件傳值可以使用props的方式,prop的類型可以是String、Number、Boolean、 Array、Object、Date、Function、Symbol。本文主要講述的是引用類型,即以下文章中的prop類型爲Object。

在開發某些功能的時候,不可避免地我們需要修改prop來達到我們目的,vue官網中提到“不應該在一個子組件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制檯中發出警告“,然而對於引用類型,我們一般性只會修改prop的部分屬性,所有隻要引用沒變,瀏覽器的控制檯就不會發出警告。這就創造了產生bug的詭異場景-"你不知道父組件傳進來的prop到底是在哪個組件被修改的。"

vue官網中提到了兩種試圖變更一個prop的情形,但是例子中展示的是基本類型的prop。最重要的關注點是官網demo下面的警示內容:“注意在 JavaScript 中對象和數組是通過引用傳入的,所以對於一個數組或對象類型的 prop 來說,在子組件中改變變更這個對象或數組本身將會影響到父組件的狀態。”

因爲 prop 是引用類型,在不用深拷貝的情況下,直接就能修改父組件數據,而且瀏覽器的控制檯並不會發出警告,因爲引用都是一樣的。當代碼中大量充斥着屬性修改時,你無法快速定位到是什麼操作修改了 prop,所以個人提倡顯式提交修改到父組件即,$emit('update:object',objectCopy),這樣就能明確確定是在子組件的這個位置處修改了 prop,當然這樣做的前提是得在父組件傳進子組件的相關屬性前加上 sync 修飾符。

在用了深拷貝的情況下,子組件和父組件相當於脫離開來,子組件內部的修改在沒有顯式提交修改到父組件時,是不會影響到父組件的數據的。

發個demo瀏覽一下

export default { name: 'Children', props: { objItem: { type: Object } }, data() { return { // 僅出於演示用這個作爲深拷貝方法。 internalObjItem: JSON.parse(JSON.stringify(this.objItem)); } }, methods: { handleChange() { this.internalObjItem.age++; // this.$emit('update:objItem', this.internalObjItem); // 顯式提交以修改父組件數據 } } }; export default { name: 'Parent', data() { return { objItem: { name: 'hua', age: 18, }; } }, };

總結

對於一個數組或對象類型的 prop 來說,在子組件中改變變更這個對象或數組本身將會雖然會影響到父組件的狀態,但實際還是卻決於團隊的開發方式趨向於用哪種方法,以便後期維護。

相關文章