iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 13
0
Modern Web

Vue.js 30天系列 第 13

Vue.js 13 - 組件/元件(Component) - 用途及使用方式

這篇是 Vue Instance 和基本結構的延伸,請參考

前面的範例,因為功能簡單,不見得複雜到需要切分。

隨著需求不斷增加,原本單純的 Vue Instance 漸漸變得複雜,掃過一遍都要按好幾次 Page Down,有種既視感吧 絕對不是說工作的專案

哎呀眼睛業障重啊~

這時你就需要
http://ithelp.ithome.com.tw/upload/images/20161228/201034246QsKu0d4Bl.jpg

組件/元件宣告 和 註冊

Vue 提供的收納方式很多種,Component 是其中最泛用的一種,Vue Instance 的縮影,用以將部分功能原始碼(template/js)切割,使得團隊成員更容易抓出特定功能的程式片段。

既然是縮影,先來個比較

Vue Instance

new Vue({
	/* Instance 有掛載點 */
	el: '#app',
	
	data: {},
	methods: {}
})

全域組件(Global Component)

Vue.component('menu-section', {
	/* 組件沒有單一掛載點,因此僅有樣板定義 */
	template: '<ul><li>menuItem</li></ul>',
	
	data: function() {
		return {};
	},
	methods: {}
})

有些屬性,例如跟生命週期相關的hook尚未提到,
但你看得出差異很小,說它是縮影不為過。


那麼動手抽組件試試,
拿 02範例 來講,改造前

<div id="app">
    {{ message }}
    <ul>
    	<li v-for="item in menuItems">{{ item.text }}</li>
    </ul>
    <p>{{ text }}</p>
</div>

<script>
var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!',
        /* menu-section */
        menuItems: [{
            text: 'About me'
        }, {
            text: 'Articles'
        }, {
            text: 'contact'
        }],
        /* description-section */
        text: 'Hello, I am Ralph.'
    }
});
</script>

僅有兩個區塊,若沒註解,你得花一點時間先找出 menu-section 用到的部分。

改造後,從 template 就看得出功能區塊,

<div id="app">
    {{ message }}
    <menu-section></menu-section>
    <description-section></description-section>
</div>

<script>
Vue.component('menu-section', {
	template: '<ul><li v-for="item in menuItems">{{ item.text }}</li></ul>',
	data: function() {
		return {
			menuItems: [{
			    text: 'About me'
			}, {
			    text: 'Articles'
			}, {
			    text: 'contact'
			}]
		};
	}
});

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    },
    components: {
    	'description-section': {
            template: '<p>{{ text }}</p>',
            data: function() {
                return {
                    text: 'Hello, I am Ralph.'
                }
            }
        }
    }
});
</script>

你可以隨著需求掛載元件
只在單一 Instance 用到的,註冊在其 components 屬性底下。

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    },
    components: {
    	'description-section': {
            template: '<p>{{ text }}</p>',
            data: function() {
                return {
                    text: 'Hello, I am Ralph.'
                }
            }
        }
    }
});

稱為 局部註冊(Local Registration)

有時你的頁面有多個 Instance,註冊一樣的 Component 定義,有點累贅吧?

<div id="app1">
    <menu-section></menu-section>
    <description-section></description-section>
</div>
<div id="app1">
    <menu-section></menu-section>
</div>

<script>
Vue.component('menu-section', {
	template: '<ul><li v-for="item in menuItems">{{ item.text }}</li></ul>',
	data: function() {
		return {
			menuItems: [{
			    text: 'About me'
			}, {
			    text: 'Articles'
			}, {
			    text: 'contact'
			}]
		};
	}
});

var app1 = new Vue({
    el: '#app1'
    /* 有註冊 <description-section> */
});
var app2 = new Vue({
    el: '#app2'
});
</script>

有另一種 - 全域註冊(Global Registration),讓 Instance 皆可使用


其他宣告方式

也許我們的組件會根據註冊在哪,有不同語意名。
就推薦你用 Vue.extend 方法,將組件定義拆出來。
(這個做法在 Vue file 寫法極為常見)

<div id="app1">
    <menu-section></menu-section>
</div>
<div id="app1">
    <my-menu></my-menu>
</div>

<script>
var MenuItem = Vue.extend({
	template: '<ul><li v-for="item in menuItems">{{ item.text }}</li></ul>',
	data: function() {
		return {
			menuItems: [{
			    text: 'About me'
			}, {
			    text: 'Articles'
			}, {
			    text: 'contact'
			}]
		};
	}
});

var app1 = new Vue({
    el: '#app1'
    components: {
        'menu-section': MenuItem
    }
});
var app2 = new Vue({
    el: '#app2',
    components: {
        'my-menu': MenuItem
    }
});
</script>

補充

組件化(Component) 近年在前端頗為流行,不論 Polymer、ng1 Directive、React、到ng2 Component,都是呼應這概念。而 Vue 除了 Component 以外,提供 Vue file 寫法,也將 style 整合至單一檔案。


圖片來源一


上一篇
Vue.js 12 - 表單輸入綁定
下一篇
Vue.js 14 - 組件/元件(Component) - 包裝方式及內部狀態
系列文
Vue.js 30天30

1 則留言

0
class90431
iT邦新手 5 級 ‧ 2019-04-26 14:01:00

嗨你好,
請問文中這部分第二個 id 是不是要改成 app2 呢?
https://ithelp.ithome.com.tw/upload/images/20190426/2011498962YMMHYnl1.png

我要留言

立即登入留言