本系列將介紹 Rails with Vue 的基本概念,並且以一個簡單的專案 Todo 來說明如何使用 Rails with Vue。我將透過這一系列的文章記錄我學習的過程,並且將我所學到的知識分享給大家。
- 【Day 01】淺入淺出 Rails with Vue - Before We Begin
- 【Day 02】淺入淺出 Rails with Vue - Vue 的基本概念 - 1
- 【Day 03】淺入淺出 Rails with Vue - Vue 的基本概念 - 2
- 【Day 04】淺入淺出 Rails with Vue - Vue 的基本概念 - 3
- 【Day 05】淺入淺出 Rails with Vue - Vue 的基本概念 - 4
- 【Day 06】淺入淺出 Rails with Vue - Vue 的基本概念 - 5
- 【Day 07】淺入淺出 Rails with Vue - Vue 的基本概念 - 6
- 【Day 08】淺入淺出 Rails with Vue - Vue 的基本概念 - 7
在 Vue 中,在運算資料時大部分都是透過 computed properties
來達成,但有某些時候用 watchers
會比較方便,例如執行 asynchronous
或 costly
的運算時,這時候就可以使用 watchers
來達成。
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<!-- Since there is already a rich ecosystem of ajax libraries -->
<!-- and collections of general-purpose utility methods, Vue core -->
<!-- is able to remain small by not reinventing them. This also -->
<!-- gives you the freedom to use what you're familiar with. -->
<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: {
// whenever question changes, this function will run
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created: function () {
// _.debounce is a function provided by lodash to limit how
// often a particularly expensive operation can be run.
// In this case, we want to limit how often we access
// yesno.wtf/api, waiting until the user has completely
// finished typing before making the ajax request. To learn
// more about the _.debounce function (and its cousin
// _.throttle), visit: https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
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>
在這個範例中,我們使用了 watchers
來監聽 question
的變化,當 question
變化時,我們會呼叫 debouncedGetAnswer
來取得答案。debouncedGetAnswer
是透過 lodash
的 debounce
來達成,這個函式會在 500ms
後執行,這樣可以避免使用者在輸入時,每輸入一個字就會呼叫 getAnswer
來取得答案,這樣會造成效能上的問題。
在 Vue 中,比較常用的需求是根據資料的變化來改變元素的樣式,這時候就可以透過 v-bind:class
來綁定 class,也可以透過 v-bind:style
來綁定 style。
我們可以 v-bind:class
來綁定 class 並動態改變 class 的值,這時候可以使用 object syntax
來達成。
<div v-bind:class="{ active: isActive }"></div>
在這個範例中,我們使用 v-bind:class
來綁定 class,並且使用 object syntax
來綁定 active
這個 class,當 isActive
的值為 true
時,active
這個 class 會被加入到元素中,當 isActive
的值為 false
時,active
這個 class 會被移除。
也可以有 多個 class
來綁定,只要在 object syntax
中加入多個 key-value
,並且和 plain class 共存。
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>
配合以下的資料:
data: {
isActive: true,
hasError: false
}
會產生以下的 HTML:
<div class="static active"></div>
當 isActive
或 hasError
的值改變時,active
或 text-danger
這個 class 也會跟著改變。例如當 hasError
的值改為 true
時,會產生以下的 HTML:
<div class="static active text-danger"></div>
被綁定的 object 不一定要 inline,例如以下的 classObject
,也會產生相同的結果:
<div v-bind:class="classObject"></div>
搭配以下的資料:
data: {
classObject: {
active: true,
'text-danger': false
}
}
除此之外我們也可以使用 computed property
來綁定 class,例如以下的 computedClassObject
<div v-bind:class="computedClassObject"></div>
data: {
isActive: true,
error: null
},
computed: {
computedClassObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
在這個範例中,我們使用 computed property
來綁定 computedClassObject
,當 isActive
和 error
的值改變時,computedClassObject
也會跟著改變。