這篇是 Vue Instance 和基本結構的延伸,請參考
前面的範例,因為功能簡單,不見得複雜到需要切分。
隨著需求不斷增加,原本單純的 Vue Instance 漸漸變得複雜,掃過一遍都要按好幾次 Page Down,有種既視感吧 絕對不是說工作的專案 ?
哎呀眼睛業障重啊~
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 整合至單一檔案。
圖片來源一