超緊繃!30天Vue.js學習日記 監聽屬性&計算屬性
大家好,今天我要介紹的是Vue中的監聽屬性(watch)以及計算屬性(computed),並且參考官網做一個簡單的比較,然後標題的部分比較正常單純只是因為我沒梗了XD
在模板語法中,是允許我們在雙括號內做一些簡單的邏輯運算的,不過,若放入太多的邏輯會使我們難以去維護模板:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
因此,計算屬性就出現了,我們可以將任何複雜的邏輯都放入計算屬性當中:
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
<script>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 計算屬性的getter
reversedMessage: function () {
// `this` 指向 vm 實例
return this.message.split('').reverse().join('')
}
}
})
</script>
在上述範例中,只要message的值改變, reversedMessage()
就會重新執行一次。
當然,我們同樣可以使用methods去做出同樣的效果:
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
雖然在這邊看不出差別,不過實際上,methods與computed有著不小的差異:
Computed會將計算結果做緩存,當相依的資料改變時,Computed才會再次計算,而methods則不同,只要綁定的物件重新渲染,它就會再次計算,即使function內相依的值沒有改變也是一樣,對於簡單的組件可能沒差,但是假設今天我們使用的function計算出的結果相依於其他的計算屬性,這樣一來一往,就會有巨大的性能差異!
若我們希望資料a變動時,資料b也做出相對應的變動,我們可能就會使用監聽屬性,但是在這邊,官方文件告訴我們不要濫用它,要多多使用計算屬性。
以此為範例:
<div id="demo">{{ fullName }}</div>
若我們使用watch:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
若我們在這邊使用Computed則可以少打不少的code,畢竟上面的兩個function基本上是一樣的。
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
高下立判(茶)
不過官方也有提到,watch也不是如此不堪,若我們今天要訪問一個API,並在等待過程中設置一個等待狀態,我們就必須使用watch,這邊一樣引用官網提供的code:
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<!—-因為 AJAX 和通用工具的發展已經相當成熟,Vue 核心代碼沒有重複-->
<!--提供這些功能以保持精簡。我們也可以使用自己熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 改變,就執行該函式
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created: function () {
// `_.debounce` 是一個透過 Lodash 限制操作频率的函式。
// 在這個例子中,我们希望限制user訪問 yesno.wtf/api 的频率
// AJAX 請求直到用戶輸入完畢才會送出。
// 相關補充:https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
this.answer = '不打問號的話還是個問句嗎?'
return
}
this.answer = '讓我想想...'
var vm = this
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
}
}
})
</script>
上述的範例有使用到axios,不過在這裡我們把重點放在watch的功用,axios在遙遠的未來…會提到的XDD
貼心如我,在這邊一樣提供本日範例供讀者下載:
https://drive.google.com/open?id=17WA7LlMGgMxwBSylRwAFc8iyPwsafUwB
今天的介紹就到這邊結束,我們明天見啦!掰掰~