從原型鏈的角度看 -> 為什麼 Vue 組件中的 data 必須是一個 Function 函數

aivon
3 min readFeb 22, 2021

--

為什麼 Vue 組件中的 data 必須是一個 Function 函數?

在 Vue 官網中對此問題的解釋:

一個組件的 data 選項必須是一個函數,因此每個實例可以維護一份被返回對象的獨立的拷貝

data: function(){     
return {
count: 0
}
}

老實說,第一次看官網這段中文解釋的時候真沒特別清楚。讓我們再看看英文版本的解釋吧:

a component’s data option must be a function, so that each instance can maintain an independent copy of the returned data object.

url: https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function

大致明白了 因為組件是用來複用的,如果組件中的 data 是一個對象,那麼這樣作用域沒有隔離,子組件中的 data 屬性值會相互影響,因此 Vue 組件中的 data 必須是一個函數,這樣每個實例之間的 data 屬性值將不會互相影響。

道理都能看懂,但還是總覺得沒有大徹大悟的感覺。於是乎,看到網路上幾篇文章的解釋後,更清楚為什麼必須得是函數了:

Object 是引用數據類型,所以如果組件中的 data 是一個對象 而非 函數時,每個實例的 data 就都是存在同一個地址,那意味著 當一個數據 發生改變的同時 會牽連其他實例內的數據進行變更。

JavaScript 只有函數能構成作用域。當 Data 是一個函數時,每個組件實例都有自己的作用域,每個實例相互獨立,不會相互影響。

const MyComponent = function() {}; 
MyComponent.prototype.data = {
a: 1,
b: 2,
}
const component1 = new MyComponent();
const component2 = new MyComponent();
// 上面實例化出來兩個組件實例 就是通過 <my-component> 調用 創建的兩個實例
component1.data.a === component2.data.a; // true;

component1.data.b = 5;
component2.data.b // 5

若兩個實例同時引用一個對象,當修改其中一個屬性的時候,另一個實例也會跟著修改。

兩個實例應該有自己各自的域才能維護好一份獨立的數據拷貝,因此需要通過下面方法進行處理:

const MyComponent = function() {     
this.data = this.data();
};
MyComponent.prototype.data = function() {
return {
a: 1,
b: 2,
}
};

這樣每一個實例的 data 屬性都是獨立的,不會相互影響了。

這是因為 JS 本身特性帶來的,與 Vue 本身設計無關。

現在再來看看官網的解釋,是不是更清晰了呢?

“一個組件的 data 選項必須是一個函數,因此每個實例可以維護一份被返回對象的獨立的拷貝”

Reference

《Vue 组件 data为什么是函数?》博客園 — 最骚的就是你 https://www.cnblogs.com/libin-1/p/6878057.html

《为什么vue中data必须是一个函数》簡書 — 牧码的星星 https://www.jianshu.com/p/839cbef3be41

--

--