0%

Vue 筆記 - 使用 X-template 建立元件

vue.js

本次練習重點

使用 x-template 的方式建立元件,並且可以使該元件能重複使用,下方有一個 table 的標籤,目前該標籤是可以使用的,假如說今天是做一個後台系統,此元件功能可以被不同頁面使用,這時候共用的元件就很重要了。

  • 使用 x-template 建立表格元件
  • 使用 is 掛載 template
  • 使用 prop 傳遞資料
  • 說明局部註冊全域註冊

HTML

1
2
3
4
5
6
7
8
9
10
<table class="table">
<thead></thead>
<tbody>
<tr v-for="(item, key) in data" :item="item" :key="key">
<td>{{ item.name }}</td>
<td>{{ item.cash }}</td>
<td>{{ item.icash }}</td>
</tr>
</tbody>
</table>

Vue

在 Vue 物件中已經有一個 data 資料,共有四筆,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
data: [
{
name: "小明",
cash: 100,
icash: 500,
},
{
name: "杰倫",
cash: 10000,
icash: 5000,
},
{
name: "漂亮阿姨",
cash: 500,
icash: 500,
},
{
name: "老媽",
cash: 10000,
icash: 100,
},
];

X-template 起手式

  1. 首先在 Vue 物件實體上方新增一個 Vue.component() 的方法,記得 Vue 要大寫!
  2. 方法內前面是要輸入新建立的元件名稱,後面的物件要放的是第一個屬性是 template:'newComponentTemplate',如下方所示。
  3. 在原本的 <script> 標籤上建立一個新的 <script> 標籤,其 id 名稱對應新建立的元件 template 名稱,要使用 # 字號,因為對應的是 HTML 的 id
  4. 在 HTML 中加入該新元件的名稱標籤。

<script type="text/x-template" id="newComponent"></script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<div id="app">
<new-component></new-component>
<table class="table">
<thead></thead>
<tbody>
<tr v-for="(item, key) in data" :item="item" :key="key">
<td>{{ item.name }}</td>
<td>{{ item.cash }}</td>
<td>{{ item.icash }}</td>
</tr>
</tbody>
</table>
</div>

<script type="text/x-template" id="newComponent"></script>
<script>
Vue.component("new-component", {
template: "#newComponent",
});

var app = new Vue({
el: "#app",
data: {
data: [
{
name: "小明",
cash: 100,
icash: 500,
},
{
name: "杰倫",
cash: 10000,
icash: 5000,
},
{
name: "漂亮阿姨",
cash: 500,
icash: 500,
},
{
name: "老媽",
cash: 10000,
icash: 100,
},
],
},
});
</script>

整理程式碼

建立完後在把原本 HTML 中的 tr 標籤內容也貼到新元件的 <script> 的標籤內,並將 v-for:bind:key 等綁定的方法移到新元件的 HTML 標籤中,程式碼會如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="app">
<table class="table">
<thead></thead>
<tbody>
<new-component
v-for="(item, key) in data"
:item="item"
:key="key"
></new-component>
</tbody>
</table>
</div>

<script type="text/x-template" id="newComponent">
<tr>
<td>{{ item.name }}</td>
<td>{{ item.cash }}</td>
<td>{{ item.icash }}</td>
</tr>
</script>

完成後會發現畫面什麼都沒有…Chrome 的開發者工具會跳錯表示,item 並沒有被定義,但其實是有定義的。

透過 Vue 的開發者工具可以看到資料的確有讀取到,

vue dev

原因是元件之間的資料是獨立且分開的,目前建立的資料是在新的元件內,也因為這個特性,外層的元件當然讀不到資料,之前已經知道如果外層要傳遞資料要給內層的元件使用,要使用 props 方法。

使用 props

新元件

在新元件建立一個接收外部資料屬性,也就是 props,並且給予陣列資料,因為原本的 data 是陣列,實務上也是接收 JSON 資料格式,為了不要搞混,將定義資料屬性名稱為 person,避免跟上方的 item 搞混。

1
2
3
4
Vue.component("new-component", {
props: ["person"], //新元件接收資料
template: "#newComponent",
});

HTML

新元件定義完後,就將其屬性綁定在標籤上,告訴原本的 v-foritem 資料,要傳進 綁定的的 person 屬性,這樣新元件才能接收到資料。

<new-ComponentTemplate v-for="(item, key) in data" :person="item" :key="key"></new-ComponentTemplate>

所以新元件中的 item 也要改成 person,因為現在的 item 屬性名稱為 person

1
2
3
4
5
6
7
<script type="text/x-template" id="newComponent">
<tr>
<td>{{ person.name }}</td>
<td>{{ person.cash }}</td>
<td>{{ person.icash }}</td>
</tr>
</script>

這時候畫面就會正確顯示於畫面上,但會發現跑版了…

view br

從開發人員工具檢視,會看到下方結構變這樣…

tbody

tr 跑到 tbody 外面了,因為在 HTML 的規則中 tbody 內就是放 tr 跟 td,那目前我們是放新元件的標籤,違反了這個規則,所以要調整一下寫法。

使用 is

tbody 中重新加入 <tr> 標籤,並把元件名稱放在 is 的屬性內,再將 vue 方法加入在 <tr> 中,就會變這樣。

1
2
3
4
5
6
7
8
<tbody>
<tr
is="new-component"
v-for="(item, key) in data"
:person="item"
:key="key"
></tr>
</tbody>

這樣畫面就變為正常且也吃到 CSS 的樣式了!

finish

透過開發者工具也看到 <tr> 正確放入 <tbody> 標籤內。
correct html

Vue 的開發者工具也正確顯示透過 is 動態將 <tr> 的標籤在執行時把原本的 <tr> 標籤內容替換掉的結果。

vue dev2

目前的新元件是全域註冊於 Vue 元件內,若只要局部註冊給新元件本身使用要怎麼寫?

局部註冊

將原本新元件的內容,透過另一個變數存取,

1
2
3
4
5
6
7
8
9
// Vue.component('new-component', {
// props: ['person'],
// template: '#newComponent'
// });

var childComponent = {
props: ["person"],
template: "#newComponent",
};

在 Vue 物件中,再加上一個 components 屬性,其內容為新元件的屬性名稱與變數名稱,這樣的結果與先前的會相同。

1
2
3
components: {
'new-component': childComponent
}