iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
0
Modern Web

RRR撞到不負責之 Laravel + Nuxt.js 踩坑全紀錄系列 第 18

Day 18. Vue Component 快速導讀 (2/2)

  • 分享至 

  • xImage
  •  

昨天介紹了 VueComponent 常用屬性,今天接著介紹 <template> 的資料綁定渲染以及事件

資料綁定

  • 單向資料流 v-bind::還記得昨天提到的 props 嗎? 這裡的 v-bind 就是由 parent component 提供 child component props 所需要的參數資料。

    下面以文章資訊卡為例子為例,使用 PostCard,至少需要提供 titlecontent 兩個參數。因此我們透過 v-bind:<參數名稱>="<參數值>" 的方式在文章列表頁中使用 PostCard 時帶入 post 資料,如 v-bind:title="post[0]['title']" 。 另外我們可以將 v-bind: 簡寫為 : ,如 :title="post[0]['title']

    // post card component:
    export default {
        name: "PostCard",
        props: {
            imageUrl: {
                type: String,
                default: "/post-default-image.jpg"
            },
            title: {
                type: String,
                required: true,
            },
            content: {
                type: String,
                required: true,
            },
        },        
    }
    
    <!-- post list page: -->
    <template>
        <div>
            <post-card v-bind:imageUrl="post[0]['image']"
                       v-bind:title="post[0]['title']"
                       v-bind:content="post[0]['content']">           
            </post-card>
        </div>
    </template>
    
    
    <script>
    import PostCard from '../components/PostCard';
    
    export default {
        name: "PostListPage",
        data() {
            return {
                post: [
                    {
                        image: 'http://localhost/api/v1/1/asd2349825m23d.jpg',
                        title: '獨家!兩津值勤時間與「她」共處一室!',
                        content: '<body> <p>號稱原始人滿腦子只有錢的龜有公園前派出所兩津勘吉 ... </p> </body>'
                    } 
                ],
                imageFailedMessage: "圖片連結失效"
            };
        }
    }
    </script>
    

    v-bind: 除了可以帶入 component props 所需要的資料之外,同時也可以帶入一般 dom element 的屬性資料,例如 <img :src="image" :alt="imageFailedMessage">

  • 雙向資料綁定 v-model:透過 v-bind: 將資料傳入 child component 後,如果資料在 child component 中被更改,原來的 component
    並不會被修改,例如上面範例中,假設 PostCard 修改了 this.title 的資料,post[0]['title'] 並不會改變。v-model 常用在 <input /> dom element。以下為以取得新增 post 的 title 為例。

    • 傳統作法:
      若要取得範例中 <input> 的 value 會透過 document.getElementById 等之類的方法取到 dom element,之後再進一步取值。

      <body>
          <form>
              <input id="new-post-title" />
          </form>
      </body>
      
    • Vue:
      在 Vue 當中,透過 v-model 綁定變數,當使用者在畫面輸入資料,this.title 會同步得到資料,反之亦然。

      <template>
          <form>
              <label>文章標題: </label>
              <input v-model="title" />
          </form>
      </template>
      
      <script>
      export default {
          name: "CreatNewPostPage",
          data() {
              return {
                  title: undefined,
              };
          }
      }
      </script>
      

    當我們熟於建立 component 、進行畫面的組合之後,不只是 <input /> 可以透過 v-model 讓資料雙向綁定,一般的 component 也做得到,這部分會在之後更詳細的說明。

渲染與邏輯控制

  • 顯示文字資料:在 <template> 當中,只要用雙大括號 {{ }} 夾住變數,就可以將文字顯示在畫面上,例如我們要顯示標題可以撰寫如下:

    <template>
        <div>
            <span>文章標題: <span>
            <span>{{title}}</span>
        </div>
    </template>
    
    <script>
    export default {
        name: "ViewPostPage",
        data() {
            return {
                title: "兩津與麗子! 只有兩個人留守的派出所!",
                content: "",
            };
        },
    }
    <script>
    
  • v-show:相當於 CSS 中 display 的概念。v-show="true" 為 block;v-show="false" 為 none;

  • v-if:畫面的渲染如果牽涉到條件,我們可用 v-if="<條件>", v-if-else="<條件>"v-else 三者進行控制是否渲染 (如果條件結果為 false,在 HTML 中並不會將 component 或是 dom element 產生出來,而不是單純只用 CSS 隱藏)。

    如同一般語言的 if/else, 使用 v-if-elsev-else 必須在兄弟節點的 component 或是 dom element 上綁有 v-if,例如下面範例中,我們透過 showType 變數決定以 <grid-card-list> 或是 <table-list> 作為文章列表渲染的方式。

    <template>
        <grid-card-list v-if="showType === 'grid'" :data="posts"></grid-card-list>
        <table-list v-if-else="showType === 'table'" :data="posts"></table-list>
    </template>
    
  • v-for:畫面上如果有資料需要透過迭代取得資料進行渲染,可以用 v-for 處理。渲染多篇文章的寫法如下。範例中我們會取得 posts 裡面的每篇 post 資料,並將 class="post-item" 的整個 dom 結構為樣板渲染出來。

    <template>
        <div>
            <div v-for="(ele, index) in posts" :key="index"  class="post-item">
                <div>{{ ele.title }}</div>
                <div>{{ ele.content }}</div>
            </div>
        </div>
    </template>
    
      * `posts`: 可以是陣列或是物件資料
      * `ele`:`posts` 每一次迭代的資料。陣列中的一個元素或是物件下的一個屬性值。
      * `index`:`posts` 每一次迭代的序號。陣列就是編號;物件則是屬性的 key。
      * `:key`: 只要用到 `v-for` 建議都要搭配綁定 key 參數,即便 component 或是' dom element 沒有此屬性或參數也是一樣。
    

    v-forv-if 搭配著用例如 <div v-for="..." v-if="...">,其兩者執行的結果會是先迭代再進行判斷:

    for () {
        if () {
            // ...
        }
    }
    

    如果希望先執行 v-if 就要將其寫到外面,例如下面兩段程式碼。如果很介意會多渲染出不必要的 dom element (如使用 v-if<div>),建議可以使用 <template>

    <template>
        <div>
            <div v-if="showType !== 'grid' && showType !== 'table'">
                <div v-for="(ele, index) in posts" :key="index"  class="post-item">
                    <div>{{ ele.title }}</div>
                    <div>{{ ele.content }}</div>
                </div>
            </div>
        <div>
    </template>
    

事件

雖然說 Vue 是 data-driven,但是仍然有事件 (event) 的概念及運用。

  • v-on:v-on:<事件名稱>="<要執行的 function>" 是使用事件的標準寫法,一般 HTML 事件像是「click」、「mouseover」、「keyup」...等都有支援。下面為新增 post 送出表單的按鈕事件撰寫範例:

    <template>
        <form>
            <!-- ... -->
        </form>
        <button type="button" v-on:click="submitForm"> 送出 <button>
    </template>
    <script>
    export default {
        name: 'CreatNewPostPage',
        data() {
            return {
                title: undefined,
                content: undefined,
            };
        },
        methods: {
            submitForm() {
                // ...
            }
        }
    }
    <script>
    

    在範例中可以看到 v-on:click="submitForm" submitForm 沒有帶括號 (),這是當呼叫的方法完全不需要帶參數時可以這樣寫。另外,有兩點需要留意:

    1. v-on: 可以縮寫為 @,所以上面範例可以改為 @click="submitForm"
    2. 如果要將「事件物件 (event object)」帶入呼叫方法中,會是使用 $event,例如:
      <template>
          <button @click="showEvent($event)">
      </template>
      <script>
      export default {
          methods: {
              showEvent(e) {
                  console.log(e);
              }
          }
      }
      </script>
      
    3. 我們可以在 component 中制定自己的 event,這部分會在後續細談客製 v-model 的時候一併介紹。

結合昨天的介紹,這兩天主要先簡單說明 Vue component 的寫法跟基本特性,當然更多的介紹可以詳閱官網文件。不知道大家有沒有寫過 todo-list 的練習? 是否有碰過明明 v-for 的資料已經改變,可是畫面卻不如預期? 因此明天要進一步帶大家看看 v-for 的一些眉角!


上一篇
Day 17. Vue Component 快速導讀 (1/2)
下一篇
Day 19. 啊啊啊 v-for 壞掉惹!!
系列文
RRR撞到不負責之 Laravel + Nuxt.js 踩坑全紀錄31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言