昨天介紹了 VueComponent 常用屬性,今天接著介紹 <template>
的資料綁定渲染以及事件
單向資料流 v-bind:
:還記得昨天提到的 props
嗎? 這裡的 v-bind
就是由 parent component 提供 child component props
所需要的參數資料。
下面以文章資訊卡為例子為例,使用 PostCard
,至少需要提供 title
和 content
兩個參數。因此我們透過 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-else
和 v-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-for
與 v-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 沒有帶括號 ()
,這是當呼叫的方法完全不需要帶參數時可以這樣寫。另外,有兩點需要留意:
v-on:
可以縮寫為 @
,所以上面範例可以改為 @click="submitForm"
$event
,例如:
<template>
<button @click="showEvent($event)">
</template>
<script>
export default {
methods: {
showEvent(e) {
console.log(e);
}
}
}
</script>
v-model
的時候一併介紹。結合昨天的介紹,這兩天主要先簡單說明 Vue component 的寫法跟基本特性,當然更多的介紹可以詳閱官網文件。不知道大家有沒有寫過 todo-list
的練習? 是否有碰過明明 v-for
的資料已經改變,可是畫面卻不如預期? 因此明天要進一步帶大家看看 v-for
的一些眉角!