今天在沒事重新翻閱 vue的開發文檔的時候,發現一個很好玩的東西,很開心,也感覺有必要記錄一下,也給大家分享一下,避免大家踩坑
文檔說:
注意在 JavaScript 中對象和數組是通過引用傳入的,所以對於一個數組或對象類型的 prop 來說,在子組件中改變變更這個對象或數組本身將會影響到父組件的狀態。
這句話咋一看好像是說vue的組件傳值不在準守但想數據流這個規則,其實不是這樣的,上面講了,是引用數據類型,不在遵守這個規則。
爲什麼?
這就要說說vue的組件傳值對於引用數據類型來說,是一個 淺拷貝。
首先我們要知道,js中所有的基本數據類型,像Undefined Null boolean number string 這五種基本數據類型是存儲在棧內存裏面的
比如
const nameTest = `123`
在內存棧中是這樣表示的
name | value |
---|---|
nameTest | 123 |
但是 引用數據類型 object(數組也是一種對象)不是的,它是數據放在堆內存裏面,棧裏面放置的是堆內存的內存地址
let obj = {
name:'123',
value:'12312'
}
name | value |
---|---|
obj | 數據存放的堆內存的內存地址 |
當我們父子組件進行傳值的時候。我們Props的原理其實是:
name | value |
---|---|
obj(父組件) | 數據存放的堆內存的內存地址A(A:代表堆內存的內存地址) |
數據存放的堆內存的內存地址A(A:代表堆內存的內存地址) |
我們會發現,其實我們在傳值的時候,不過是吧,棧內存複製的那一行,複製了一遍,包括裏面value值
這個時候,我們在子組件中修改的時候,其實就是改變父子組件共同引用的那個堆內存中的值,所以也會改變父組件中的數據的值
爲什麼基本數據類型就不會了?
因爲基本數據類型,Prop的時候,棧內存裏面是直接複製的。
name | value |
---|---|
nameTest(父組件) | 123 |
nameTest(子組件) | 123 |
所以,你改變子組件的值的時候,不會改變父組件的值
怎麼解決prop的淺拷貝
可以通過
JSON.Parse(JSON.String(父組件傳遞的值))
來解決
原理就是,將父組件中的堆內存中的數據,改成字符串,之後,再將字符串變成引用類型的值,放到堆內存裏面去。這個時候,父子組件堆內存中的值雖然是一樣的,但是棧內存中的value卻不一樣