iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 12
0
Modern Web

30天手把手的vue.js教學!系列 第 12

2020it邦鐵人賽-30天手把手的Vue.js教學 Day12 - 認識props屬性,從外向內的資料傳遞

tags: Vue.js ItIron2020

前言

昨天我們介紹了vue組件的概念,在之後你會慢慢了解到一個vue打造的應用程式,其實就是由一堆組件疊加起來的東西,彼此之間有很明確的上下關係,就像是一個掛在支架上的葡萄一樣,每一粒葡萄與其他葡萄向下相連,最終結實累累的一整串! 我們昨天雖然做到了將todo-list組件化,但目前的內容完全寫死,我們希望的是可以告訴那個組件現在要render怎麼樣的資料,這就需要props屬性的幫忙了,我們馬上開始吧!

問題釐清

還記得我們昨天的進度嗎? 我們最終順利地用v-for配合新註冊的組件印出了四個代辦事項,但內容卻不太正確。

todo-list

我們在父層(也就是一開始的vue實體)有著四個不同的代辦事項,我們希望能將這些todos傳進子層(也就是新建立的todo-list組件),讓它能根據傳進去的資料印出對應的結果,為此我們有幾件事情要做。

  1. 在子層設定要接收的資料,並修改todo-list template的內容
  2. 在父層使用子組件時,傳入所需要的資料

我們一步一步來吧!GOGOGO

認識props屬性

首先一樣請你先打開今天的demo
我們要做的第一步就是在我們註冊的組件中加入props屬性,設定props屬性可以讓這個元件接受來自父層傳入的資料,我知道這聽起來有些難懂,看完以下的說明就會比較有概念了!

完整的props寫法分為幾個部分

  1. 傳入的props名稱
  2. 傳入的props資料型態
  3. 傳入的選項
    如果今天你想傳一個名為todo的參數給子層,那你可以簡單地這樣寫
props: ['todo']

你自然也可以多傳幾個參數給子層,只要你需要的話

props: ['todo', 'paramA', 'paramB']

你也可以進一步給傳入的資料增加一些選項,此時則必須改為物件形式

props: {
    todo : {
      type: Object // 指定傳進來的參數必須是物件,否則報錯
    } 
  }

同時可以設定這個參數是否是必須值以及是否需要default value

props: {
    todo : {
      type: Object,
      required: true, // 此欄位必填
      default: {} // 預設值為空物件
    } 
  }

利用以上的手法,你可以預先設定傳進來的參數需要滿足哪些條件,這樣就可以先預防一些可能的錯誤! 到這邊你應該對於props的概念仍相當模糊,但只要跟著做完實作,我相信會有基本的了解,先不用緊張?

請你先在原本的程式碼中,加入以下的部分。

Vue.component("todo-list", {
  template: `
    <div class="todo-wrapper">
      <div class="todo-title">
        Write Article
      </div>
      <div class="todo-icons">
        <i class="fa fa-check" aria-hidden="true"></i>
        <i class="fa fa-trash-alt" aria-hidden="true"></i>
      </div>
    </div>
  `,
  props: {
    todo : {
      type: Object,
      required: true
    } 
  }
});

上方的寫法就是希望傳進來的參數為一個物件、且必定需要這個參數,任何一個條件沒滿足就會報錯!

根據傳進來的props修改template的內容

現在我們設定好資料傳遞的格式了,我們先複習一下傳進來的todo物件長什麼樣子,我們才有辦法去修改我們的template

{
  title: "Get dressed",
  isComplete: false
}

這樣就很清楚我們要修改的兩個部分

  1. 原本標題的部分
<div class="todo-title">Write Article</div>
  1. 綁定的class
<div class="todo-wrapper">
  // 略
</div>

請你將原本template的內容改為以下

Vue.component("todo-list", {
  template: `
    <div :class="[todo.isComplete? 'success':'error','todo-wrapper']"> // 這裡
      <div class="todo-title">
        {{todo.title}} // 還有這裡
      </div>
      <div class="todo-icons">
        <i class="fa fa-check" aria-hidden="true"></i>
        <i class="fa fa-trash-alt" aria-hidden="true"></i>
      </div>
    </div>
  `,
  props: {
    todo : {
      type: Object,
      required: true
    } 
  }
});

我們傳進來的todo物件有兩個屬性可以讓我們使用,分別是title & isComplete,我們分別修改在template中對應的部分,你可以想像我們在子元件的data屬性中多了一個todo讓我們使用,那剩下的應該就相當好懂囉!

利用v-bind在父層傳遞資料給子層

最後我們只要在父層利用v-bind將資料傳遞給子層,注意一下我們傳入的方式為

v-bind:傳入的prop名稱(你剛在子層設計的)="傳入的變數"

請你將使用todo-list的部分修改為以下

<todo-list v-for="todo in todos" :key="todo.id" :todo="todo"></todo-list>

我們先利用v-for迭代todos陣列,接著把每一個迭代到的物件傳進子層,上方的寫法你可以改寫為以下的寫法做一個比較,你會更清楚哪一個是prop,哪一個是迭代到的物件。

<todo-list v-for="item in todos" :key="item.id" :todo="item"></todo-list>

最後你會不意外的看到我們預期的結果,一個漂亮的todo list!
props

結語

我們今天介紹了props屬性與最基本的父子層資料傳遞,props在一開始接觸實確實很容易讓人困惑,你只要把它想成從父層那邊拿個data屬性來用,其他的部分就跟你平常用data屬性內的變數進行渲染或計算沒有任何差別!
這是一個實務上極端常見的技巧,你也可以試著利用今天的範例多傳一些參數進子層操作,應該會再更有概念一些! 那我們就明天見囉!

此文章同步發布於個人部落格,有興趣的大大也可以來參觀一下:D


上一篇
2020it邦鐵人賽-30天手把手的Vue.js教學 Day11 - 認識Vue Components
下一篇
2020it邦鐵人賽-30天手把手的Vue.js教學 Day13 - 認識emit客製事件,由內向外的資料傳遞
系列文
30天手把手的vue.js教學!30

尚未有邦友留言

立即登入留言