本系列將介紹 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
- 【Day 09】淺入淺出 Rails with Vue - Vue 的基本概念 - 8
- 【Day 10】淺入淺出 Rails with Vue - Vue 的基本概念 - 9
- 【Day 11】淺入淺出 Rails with Vue - Vue 的基本概念 - 10
- 【Day 12】淺入淺出 Rails with Vue - Vue 的基本概念 - 11
- 【Day 13】淺入淺出 Rails with Vue - Vue 的基本概念 - 12
- 【Day 14】淺入淺出 Rails with Vue - Vue 的基本概念 - 13
- 【Day 15】淺入淺出 Rails with Vue - Vue 的基本概念 - 14
- 【Day 16】淺入淺出 Rails with Vue - Vue 的基本概念 - 15
- 【Day 17】淺入淺出 Rails with Vue - Vue 的基本概念 - 16
- 【Day 18】淺入淺出 Rails with Vue - Vue 的基本概念 - 17
當我們建立 <blog-post>
時,component 的 template 一定不只有 title 這麼單純,
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
至少,還會有 content
<h3>{{ title }}</h3>
<div v-html="content"></div>
但假如我們這麼做的話,Vue 會報錯,並且解釋 every component must have a single root element
,也就是說,每個 component 都必須有一個單一的 root element。
這時候,我們可以使用 <div>
包起來,讓它變成一個單一的 root element (div)。
<div class="blog-post">
<h3>{{ title }}</h3>
<div v-html="content"></div>
</div>
而隨著 component 漸漸長大,我們可能不只需要 title 和 content,還需要其他的東西,像是 publishedAt、comments 等等,
這時候如果每個都透過定義一個 prop
來傳遞,那麼會變得很麻煩,
如以下範例中,我們需要傳遞 title、content、publishedAt、comments 這 4 個 prop
。
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
v-bind:content="post.content"
v-bind:publishedAt="post.publishedAt"
v-bind:comments="post.comments"
></blog-post>
為了解決這個問題,我們可以使用 v-bind
來傳遞一個單一物件 prop
來解決。
如以下範例中,我們使用 v-bind:post="post"
來傳遞一個物件 post
prop,這個 prop
包含了 title、content 這 2 個資料。
```html
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
`
})
以上範例中我們使用了
JavaScript’s template literal
來達成多行 template 並增加可讀性,但這樣的方法在 IE 中不支援,如果你需要支援 IE,可以使用newline escapes
來達成多行 template。
隨著 component 的漸漸長大,我們可能會需要在 component 中觸發一些事件,並且在 parent component 中監聽這些事件,並且執行一些動作。
例如我們希望新增一個 accessibility feature
功能來讓使用者可以可以將文章的內容放大檢視。
在 parent 中,我們可以新增一個 postFontSize
的 data 用來支援這個功能。
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
}
})
接著我們可以用這個 postFontSize
的 data 來控制 blog-post
component 的樣式。
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></blog-post>
</div>
</div>
在 component 中,我們可以新增一個 button
來讓使用者可以點擊來放大文章內容。
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button>
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
`
})
想當然爾,只把 button 加上去當然不會動,會動很可怕,
我們希望當使用者點擊 Enlarge text
按鈕時,可以觸發一個事件,並且在 parent 中監聽這個事件,並且執行一些動作。
幸運的是,Vue instance 提供了一個 custom system event 來支援這個功能。
parent (new Vue()
) 可以使用 v-on
來監聽任何來自 child component 的事件。
例如以下範例中,我們監聽 enlarge-text
事件,並且在觸發時,將 postFontSize
的值增加 0.1。
<blog-post
...
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
接著 child component 可以使用 this.$emit
來觸發一個事件,讓 parent component 可以監聽到。
使用的方法就是 this.$emit('event-name')
,例如以下範例中,我們在 Enlarge text
按鈕的 click event 中觸發 enlarge-text
事件。
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
當 child component 發射 enlarge-text
事件時,parent component 就會接收到並且執行 postFontSize += 0.1
這個動作,真 ㄅㄧㄤˋ。