我們知道,vue有一個重要的理念就是組件化,即將重復使用的功能點抽提出來作為組件,需要使用的頁面只需要引用該組件即可得到相應的功能點。
而組件化的一個重要特性就是作用域隔離,即一個組件實例擁有一個私有的作用域,當在頁面中引用了該組件之后,只有該組件實例能訪問該作用域。
但是當在同一個頁面多次使用同一個組件的時候,如果只創建了一個實例,但是卻對這個實例調用了兩次,這兩個調用就會造成相互干擾的問題,因為這時候這兩個調用訪問的是同一個作用域。比如有現在有一個yanggb組件,我引入到我的頁面中(創建了一個組件實例),然后調用兩次(在頁面上調用組件實例兩次),那么當我給第一個調用綁定的對象變量的一個屬性賦值了100,那么第二個調用綁定的同一個對象變量的該屬性也會被賦值100,因為這兩個調用在同一個作用域內綁定了同一個對象變量,而JavaScript內一切對象皆為引用,也就導致第二個調用的值跟着第二個調用的值變化了。
// 引用yanggb組件並創建一個實例 const yanggb = () => import('@/components/yanggb') // 注冊該組件實例 components: { yanggb } // 在頁面上兩次調用該組件實例 <yanggb :value="100"></yanggb> <yanggb></yanggb>
這個時候,如果該組件是直接顯示的:value屬性中綁定的值的話,那么兩個調用都會顯示100的值。
其實解決辦法在這里已經呼之欲出了,既然創建一個實例調用兩次會相互影響,那么我創建兩個實例分別調用一次不就不會相互干擾了嗎?我們來試一下。
// 引用同一個yanggb組件但創建兩個個實例 const yanggb = () => import('@/components/yanggb') const yanggb1 = () => import('@/components/yanggb') // 注冊兩個組件實例 components: { yanggb, yanggb1 } // 在頁面上分別調用兩個組件實例 <yanggb :value="100"></yanggb> <yanggb1></yanggb1>
那么這個時候因為兩個實例擁有相互獨立的私有作用域,也就不會導致相互干擾的結果了,第二個實例的調用不會顯示100的值。
PS:以上的【實例】和【調用】相關字眼是個人的理解,只是為了方便理解,並不一定正確。
另外,在解決問題的過程中,查到一些相關的解決方案,其中一個是使用JSON.stringify()和JSON.parse()兩個方法配合使用來RE-雙向綁定(個人理解是強行派生出新的對象,解除對原對象的引用,並將該新對象綁定到該組件調用上),但是總覺得有點奇怪,因為這樣只是在同一個作用域內解除了對同一個對象的多次引用,不太符合組件化的設計理念與特性,並可能產生意料之外的問題,不是很喜歡這種方法。
"很多人都在告訴我要懂事,但是沒有一個人告訴我要快樂。"