1.vue中父子組件通信最常用的方式是props和$emit,通常來說,父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這樣會防止從子組件意外改變父級組件的狀態,從而導致你的應用的數據流向難以理解。
但是當父組件的傳值是數組或者對象時,子組件中不僅能夠直接修改,還不會報錯,在子組件中改變這個對象或數組本身將會影響到父組件的狀態。
父組件代碼:
<div style="width: 600px;height: 400px;border: 1px solid red;"> <span style="font-size: 30px;">父組件區域:</span> <div>傳給子組件的值【toChildrenData】:{{toChildrenData}}</div> <div> <children :toChildrenData="toChildrenData"></children> </div> </div> data () { // 這里存放數據 return { toChildrenData: { name: '李四', age: 22 } } }
子組件代碼:
<template> <div class="" style="width: 400px;height: 300px;margin: 30px auto;border: 1px solid #0000ff"> <span style="font-size: 30px;">子組件區域:</span> <div>父組件傳過來的值【toChildrenData】:{{toChildrenData}}</div> <input type="text" v-model="toChildrenData.name"> </div> </template> props: { toChildrenData: { type: Object, default () { return {} } } },
事例效果:
可以看到,修改props傳過來的值,是可以修改的,父組件里面也會跟着修改。
2.接下來分析下出現這種情況的原因:
(1)JavaScript 數據類型
值類型(基本類型):字符串(String)、數字(Number)、布爾(Boolean)、對空(Null)、未定義(Undefined)、Symbol。
引用數據類型:對象(Object)、數組(Array)、函數(Function)。
(2)內存空間:
要理解 JavaScript 在運行過程中數據是如何存儲的,就得先搞清楚其存儲空間的種類
在 JavaScript 的執行過程中, 主要有三種類型內存空間,分別是代碼空間、棧空間和堆空間,其中的代碼空間主要是存儲可執行代碼的,棧空間就是調用棧,是用來存儲執行上下文的,堆空間是用來儲存引用數據類型的。
這些概念不懂也沒關系,就是這么個東西:js執行的時候,會把基本類型的數據保存在棧空間中,引用類型的數據保存在堆空間中
var name = '李四'
var age = 22
var chlidrenData = {
name: '李四',
age: 22
}
var newchlidrenData = chlidrenData
看一個簡單的示意圖:
從上圖可以看到,對象類型是存放在堆空間的,在棧空間中只是保留了對象的引用地址,當 JavaScript 需要訪問該數據的時候,是通過棧中的引用地址來訪問的,所以,父組件傳遞給子組件的,實際上只是一個引用地址,當子組件修改這個對象時,是真的修改了在堆空間中保存的數值,當然父組件中的值也會發生變化,但是引用地址沒有進行修改,所以並沒有報錯。
3.上面簡要分析了一下vue組件通信中,父組件傳一個對象給子組件,子組件可以直接修改這個數據,並且可以影響父組件的問題,里面涉及到堆空間、棧空間等JavaScript數據類型以及瀏覽器底層原理的東西,感興趣的話可以閱讀一下相關知識點。