Vue 元件data為什麼必須是函式?

weixin_34249678發表於2017-10-21

在建立或註冊模板的時候,傳入一個data屬性作為用來繫結的資料。但是在元件中,data必須是一個函式,而不能直接把一個物件賦值給它。

Vue.component('my-component', {
  template: '<div>OK</div>',
  data() {
    return {} // 返回一個唯一的物件,不要和其他元件共用一個物件進行返回
  },
})複製程式碼

你在前面看到,在new Vue()的時候,是可以給data直接賦值為一個物件的。這是怎麼回事,為什麼到了元件這裡就不行了。

你要理解,上面這個操作是一個簡易操作,實際上,它首先需要建立一個元件構造器,然後註冊元件。註冊元件的本質其實就是建立一個元件構造器的引用。使用元件才是真正建立一個元件例項。所以,註冊元件其實並不產生新的元件類,但會產生一個可以用來例項化的新方式。

理解這點之後,再理解js的原型鏈:

var MyComponent = function() {}
MyComponent.prototype.data = {
  a: 1,
  b: 2,
}
// 上面是一個虛擬的元件構造器,真實的元件構造器方法很多

var component1 = new MyComponent()
var component2 = new MyComponent()
// 上面例項化出來兩個元件例項,也就是通過<my-component>呼叫,建立的兩個例項

component1.data.a === component2.data.a // true
component1.data.b = 5
component2.data.b // 5複製程式碼

可以看到上面程式碼中最後三句,這就比較坑爹了,如果兩個例項同時引用一個物件,那麼當你修改其中一個屬性的時候,另外一個例項也會跟著改。這怎麼可以,兩個例項應該有自己各自的域才對。所以,需要通過下面方法來進行處理:

var MyComponent = function() {
  this.data = this.data()
}
MyComponent.prototype.data = function() {
  return {
    a: 1,
    b: 2,
  }
}複製程式碼
var MyComponent = function() {
  this.data = this.data()
}
MyComponent.prototype.data = function() {
  return {
    a: 1,
    b: 2,
  }
}
function () {
  return {
    a: 1,
    b: 2,
  }
}
var component1 = new MyComponent()
var component2 = new MyComponent()
undefined
component1.data===component2.data
false
component1.data
Object {a: 1, b: 2}    複製程式碼

這樣每一個例項的data屬性都是獨立的,不會相互影響了。所以,你現在知道為什麼vue元件的data必須是函式了吧。這都是因為js本身的特性帶來的,跟vue本身設計無關。其實vue不應該把這個方法名取為data(),應該叫setData或其他更容易立即的方法名。


相關文章