在 Vue
中,我們定義數(shù)據(jù)使用 data
.
在 Vue
的根節(jié)點里,它是一個對象.
var app = new Vue({
el: '#app',
data: {
msg: 'this is msg'
})
在components
中,它是一個函數(shù),內(nèi)部返回一個對象
export default {
name: 'cart-buy-button',
data () {
return {
testNum: 0,
addCounter: 0,
removeCounter: 0
}
}
}
因為 vue 根節(jié)點,在整個vue單頁面實例中,它有且只有一個,所以
data
可以設(shè)置成一個Object{}
但是子組件可能會多次實例化和調(diào)用,所以為了確保子組件的數(shù)據(jù)的獨立性和隔離性,需要使用data(){return{}}
的方法.每次返回一個新的對象.
數(shù)據(jù)流的單向流動.
在 Vue
中,我們使用插值表達(dá)式,往某個非表單
元素中插入 data
里的數(shù)據(jù)時,數(shù)據(jù)是單向流動的.
<div id='app'>
<div>{{msg2}}</div>
<button @click="changeDataMsg">change.data.msg</button>
</div>
var app = new Vue({
el: '#app',
data: {
msg2: 'this is msg'
},
methods: {
changeDataMsg() {
this.msg2 = Math.random(1000).toString().substring(0, 2) + this.msg2
}
}
結(jié)果:
在初學(xué)vue的時候,覺得挺新奇.
過了幾天,覺得就是這樣的.
在過了幾天就發(fā)現(xiàn),原來是
Vue
在實例化的時候會把data
里的屬性使用ES5
提供的Object.defineProperty
重新定義一遍,并設(shè)置其屬性的get
和set
也就是說,我們給定的data屬性,其內(nèi)部是有可能這么一段代碼.
let obj = {
name: '李四',
age: 22
}
let defaultName = '李四'
Object.defineProperty(obj, 'name', {
set(newVal) {
defaultName = newVal
// 檢測到新值,更新 dom
},
get() {
return defaultName
}
})
let defaultAge = 22
Object.defineProperty(obj, 'age', {
set(newVal) {
defaultAge = newVal
// 檢測到新值,更新 dom
},
get() {
return defaultAge
}
})
也就是說,所有(不管是根Vue還是components)的實例的data
屬性,都會被使用 Object.defineProperty
重新定義.這也就是為什么Vue
對于表單元素的雙向綁定
和非表單元素的單向數(shù)據(jù)流
屬性的基礎(chǔ).
關(guān)于 Object.defineProperty 可以參考我之前寫的一篇
Object.defineProperty 解析
非 data 屬性呢?
我們都知道,js是一本特別靈活的語言,可以很隨意的給對象添加屬性,而需要實現(xiàn)聲明.
created() {
// 在非data里定義的數(shù)據(jù),沒有被 Object.defineProperty重新定義,所以無法檢測到get,set,也不無法更新dom.
this.defineOnCreatedProperty = '這是在 created 鉤子函數(shù)里定義的變量'
},
在 created
鉤子函數(shù)里,隨意的給當(dāng)前實例添加一個 defineOnCreatedProperty
屬性,是否也支持單向數(shù)據(jù)流
&雙向綁定
呢?
<div id='#app'>
<div>{{defineOnCreatedProperty}}</div>
<button @click="changeCreatedData">change.created.data</button>
</div>
changeCreatedData() {
this.defineOnCreatedProperty = '能否檢測到改變????'
}
結(jié)果:
怎么點,都不能像 data
里定義的數(shù)據(jù)那樣,支持?jǐn)?shù)據(jù)流的特性.
原因也很簡單:
非
data
里聲明,而是你自己定義的屬性,那它就是一個普通的屬性,vue不會去對待它(使用Object.defineProperty)去重新定義.所以,就無法檢測到變化,不能檢測到變化,就無法支持所有的數(shù)據(jù)流特性了.
總結(jié)
- vue的數(shù)據(jù)流,是里用的
ES5
提供的Object.defineProperty
方法來重新定義data
數(shù)據(jù),以便獲取屬性的get/set
來檢測屬性的變化,以實現(xiàn)數(shù)據(jù)流. - 自己隨便定義的屬性,比如
this.defineOnCreatedProperty
沒有定義在data
,沒有Object.defineProperty
去重新定義此屬性以監(jiān)控set/get
,當(dāng)然就無法實現(xiàn)所謂的數(shù)據(jù)流了.