iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0
Modern Web

淺入淺出 Rails with Vue系列 第 18

【Day 18】淺入淺出 Rails with Vue - Vue 的基本概念 - 17

  • 分享至 

  • xImage
  •  

【Day 18】淺入淺出 Rails with Vue - Vue 的基本概念 - 17

前言

本系列將介紹 Rails with Vue 的基本概念,並且以一個簡單的專案 Todo 來說明如何使用 Rails with Vue。我將透過這一系列的文章記錄我學習的過程,並且將我所學到的知識分享給大家。

Components Basics

Base Example

Component 是一個可以重複使用的 Vue 實例,可以將它想像成一個自定義的 HTML 標籤,並且可以在這個標籤中傳入參數,並且在這個標籤中使用這些參數。

// Define a new component called button-counter
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

例如以上範例中,我們定義了一個名為 button-counter 的 Component,我們可以在 root Vue 實例中 new Vue 使用這個 Component

<div id="components-demo">
  <button-counter></button-counter>
</div>
new Vue({ el: '#components-demo' })

因為 Component 為可重複使用的 Vue 實例,他們可以接受像是 new Vue 的參數,例如 datacomputedwatchmethods 等等。

Reusing Components

Component 可以根據需要多次重複使用,例如以下範例中,我們定義了一個名為 button-counter 的 Component,並且在 root Vue 實例中使用了 3 次。
這 3 個 Component 會各自維護自己的 data,因為他們是來自 3 個不同的 Vue 實例,彼此獨立運作。

<div id="components-demo">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

data Must Be a Function

在建立 button-counter Component 時,你可能已經注意到 data 沒有透過 object 的方式傳入,如以下的寫法:

data: {
  count: 0
}

取而代之的是,data 必須是一個 function,透過 function 的方式回傳一個 object,這樣才能保證每個 Component 都有自己的 data

data: function () {
  return {
    count: 0
  }
}

假如上面例子中不是透過 function 的方式回傳 data,那麼所有的 Component 都會共用同一個 data,這樣就會造成所有的 Component 都會共用同一個 count,這樣就不是我們想要的結果。

Organizing Components

將應用程式 (APP) 拆分成一個個小的 Component,這樣可以讓程式碼更容易維護,也可以讓程式碼更容易重複使用。
image

舉例來說,你可能有 header、sidebar、content 這 3 個 Component,每個 Component 可能又包含在自己的 Component 中,例如 header 可能包含了 logo、navigation、search 這 3 個 Component。
要在 template 中使用這些 Component,必須要先在 Vue 實例中註冊這些 Component,這樣 Vue 才能夠知道這些 Component 的存在。
現行兩種註冊 Component 的方式,分別是全域註冊 (Global Registration) 與區域註冊 (Local Registration)。
到目前為止我們都是透過全域註冊的方式來註冊 Component,例如:

Vue.component('my-component-name', {
  // ... options ...
})

全域註冊可以使用在任何 root Vue 實例 (new Vue) 中,甚至在 subcomponents 中也可以使用。

Passing Data to Child Components with Props

在先前我們提到為一個 blog 的 posts 建立一個 Component,那時候遇到的問題是,component 無法取得 posts 相關的資料,因為 posts 是在 root Vue 實例中定義的,而 component 是在 root Vue 實例中使用的。
為了解決這個問題,我們可以透過 props 來傳遞資料給 child component。
props 是一個自定義的 attribute,你可以在 component 中像是使用 data 一樣使用 props。當 value 被傳遞給一個 prop attribute 時,它就變成了該 component 實例的一個 property。
例如在以下的範例中,我們定義了一個名為 blog-post 的 component,並且可以透過 props 來傳遞一個 title 的 attribute 給這個 component。

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

一個 Component 可以有任意數量的 prop,只要在 props 中定義即可,一但 prop 被定義,你可以傳遞任意的 string 作為 prop 的 attribute,如以下範例:

<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>

將會渲染為

<div id="blog-post-demo" class="demo">
  <h3>My journey with Vue</h3>
  <h3>Blogging with Vue</h3>
  <h3>Why Vue is so fun</h3>
</div>

然而人類是貪心的,總是想要更多,上面的範例中只傳送了 String,但是很多時候我們想傳送的是 Array 或是 Object,
如以下範例中,我們想要傳送一個包含了 idtitle 的 Array 給 blog-post component。

new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})

然後想要渲染為

<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:title="post.title"
></blog-post>

在以上的範例中,我們使用了 v-bind 指令來動態的傳遞 title 的 attribute 給 blog-post component,當你不太確定實際上要渲染的內容是什麼時,這樣的方法是很有用的,就很像 fetch data from api 一樣,你不知道實際上會拿到什麼,但是你知道你會拿到什麼。

Reference


上一篇
【Day 17】淺入淺出 Rails with Vue - Vue 的基本概念 - 16
下一篇
【Day 19】淺入淺出 Rails with Vue - Vue 的基本概念 - 18
系列文
淺入淺出 Rails with Vue30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言