Vue實例對象的數據選項

轉自https://www.cnblogs.com/xiaohuochai/p/7294208.html

前面的話

一般地,當模板內容較簡單時,使用data選項配合表達式即可。涉及到復雜邏輯時,則需要用到methods、computed、watch等方法。本文將詳細介紹Vue實例對象的數據選項

data

data是Vue實例的數據對象。Vue將會遞歸將data的屬性轉換為getter/setter,從而讓data屬性能響應數據變化

[注意]不應該對data屬性使用箭頭函數

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><div id="app"> {{ message }} </div></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var values = {message: 'Hello Vue!'} var vm = new Vue({
el: '#app',
data: values
})
console.log(vm); </script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

image

Vue實例創建之后,可以通過vm.$data訪問原始數據對象

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">console.log(vm.$data);</pre>

image

Vue實例也代理了data對象上所有的屬性

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var values = {message: 'Hello Vue!'} var vm = new Vue({
el: '#app',
data: values
})
console.log(vm.data === values);//true console.log(vm.message);//'Hello Vue!' console.log(vm.data.message);//'Hello Vue!'
</script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

被代理的屬性是響應的,也就是說值的任何改變都是觸發視圖的重新渲染。設置屬性也會影響到原始數據,反之亦然

image

但是,以_$開頭的屬性不會被Vue實例代理,因為它們可能和Vue內置的屬性或方法沖突。可以使用例如vm.$data._property的方式訪問這些屬性

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var values = {
message: 'Hello Vue!',
_name: '小火柴' } var vm = new Vue({
el: '#app',
data: values
})
console.log(vm._name);//undefined
console.log(vm.$data._name);//'小火柴'
</script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

computed

計算屬性函數computed將被混入到Vue實例中。所有getter和setter的this上下文自動地綁定為Vue實例

[注意]不應該使用箭頭函數來定義計算屬性函數

下面是關于computed的一個例子

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><div id="example">
<p>原始字符串: "{{ message }}"</p>
<p>反向字符串: "{{ reversedMessage }}"</p>
</div></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var vm = new Vue({
el: '#example',
data: {
message: '小火柴' },
computed: {
reversedMessage: function () { return this.message.split('').reverse().join('')
}
}
}) </script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

結果如下

image

這里聲明了一個計算屬性 reversedMessage 。提供的函數將用作屬性 vm.reversedMessage 的 getter

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;">console.log(vm.reversedMessage) // -> '柴火小'
vm.message = 'Goodbye' console.log(vm.reversedMessage) // -> 'eybdooG'</pre>

vm.reversedMessage 的值始終取決于 vm.message 的值。可以像綁定普通屬性一樣在模板中綁定計算屬性。當 vm.message 發生改變時,所有依賴于 vm.reversedMessage 的綁定也會更新

結果如下圖所示,vm.reversedMessage依賴于vm.message的值,vm.reversedMessage本身并不能被賦值

image

【setter】

計算屬性默認只有 getter ,不過在需要時也可以提供一個 setter

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var vm = new Vue({
data: { a: 1 },
computed: { // 僅讀取,值只須為函數
aDouble: function () { return this.a * 2 }, // 讀取和設置
aPlus: {
get: function () { return this.a + 1 },
set: function (v) { this.a = v - 1 }
}
}
})
console.log(vm.aPlus);//2
vm.aPlus = 3 console.log(vm.a);//2
console.log(vm.aDouble);//4
</script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

methods

通過調用表達式中的 methods 也可以達到同樣的效果

[注意]不應該使用箭頭函數來定義methods函數

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><div id="example">
<p>原始字符串: "{{ message }}"</p>
<p>反向字符串: "{{ reversedMessage() }}"</p>
</div></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var vm = new Vue({
el: '#example',
data: {
message: '小火柴' },
methods: {
reversedMessage: function () { return this.message.split('').reverse().join('')
}
}
}) </script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

【緩存】

對于最終的結果,兩種方式確實是相同的

然而,不同的是計算屬性是基于它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變時才會重新求值。這就意味著只要 message 還沒有發生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結果,而不必再次執行函數

相比而言,只要發生重新渲染,method 調用總會執行該函數。如下所示

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><div id="example">
<p>計算屬性: "{{ time1 }}"</p>
<p>methods方法: "{{ time2() }}"</p>
</div></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var vm = new Vue({
el: '#example',
computed:{
time1: function () { return (new Date()).toLocaleTimeString()
}
},
methods: {
time2: function () { return (new Date()).toLocaleTimeString()
}
}
}) </script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

image

假設有一個性能開銷比較大的的計算屬性A,它需要遍歷一個極大的數組和做大量的計算。可能有其他的計算屬性依賴于 A 。如果沒有緩存,將不可避免的多次執行A的getter!如果不希望有緩存,則用 method 替代

watch

Vue提供了一種通用的方式來觀察和響應Vue實例上的數據變動:watch屬性。watch屬性是一個對象,鍵是需要觀察的表達式,值是對應回調函數,回調函數得到的參數為新值和舊值。值也可以是方法名,或者包含選項的對象。Vue實例將會在實例化時調用$watch(),遍歷watch對象的每一個屬性

[注意]不應該使用箭頭函數來定義 watch 函數

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><div id="app">
<button @click="a++">a加1</button>
<p>{{ message }}</p>
</div></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var vm = new Vue({
el: '#app',
data: {
a: 1,
message:'' },
watch: {
a: function (val, oldVal) { this.message = 'a的舊值為' + oldVal + ',新值為' + val;
}
}
}) </script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

上面代碼中,當a的值發生變化時, 通過watch的監控,使message輸出相應的內容

<iframe src="https://demo.xiaohuochai.site/vue/base/b1.html" frameborder="0" width="320" height="100"></iframe>

【$watch】

除了使用數據選項中的watch方法以外,還可以使用實例對象的$watch方法, 該方法的返回值是一個取消觀察函數,用來停止觸發回調

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><div id="app">
<button @click="a++">a加1</button>
<p>{{ message }}</p>
</div></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; white-space: pre-wrap; overflow-wrap: break-word; padding: 0px; list-style-type: none; list-style-image: none; font-family: "Courier New" !important; font-size: 12px !important;"><script>
var vm = new Vue({
el: '#app',
data: {
a: 1,
message:'' }
}) var unwatch = vm.$watch('a',function(val, oldVal){ if(val === 10){
unwatch();
} this.message = 'a的舊值為' + oldVal + ',新值為' + val;
}) </script></pre>

[
復制代碼

](javascript:void(0); "復制代碼")

上面的代碼中,當a的值更新到10時,觸發unwatch(),來取消觀察。點擊按鈕時,a的值仍然會變化,但是不再觸發watch的回調函數

image
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內容,還有我對于 Vue 1.0 印象不深的內容。關于...
    云之外閱讀 5,082評論 0 29
  • Vue 實例 屬性和方法 每個 Vue 實例都會代理其 data 對象里所有的屬性:var data = { a:...
    云之外閱讀 2,246評論 0 6
  • 深入響應式 追蹤變化: 把普通js對象傳給Vue實例的data選項,Vue將使用Object.defineProp...
    冥冥2017閱讀 4,900評論 6 16
  • 一:什么是閉包?閉包的用處? (1)閉包就是能夠讀取其他函數內部變量的函數。在本質上,閉包就 是將函數內部和函數外...
    xuguibin閱讀 9,751評論 1 52
  • vue.js簡介 Vue.js讀音 /vju?/, 類似于 viewVue.js是前端三大新框架:Angular....
    LiWei_9e4b閱讀 544評論 0 0