有一篇非常棒的關(guān)于vue.js的組件的文章,寫的特別好,特別清楚,容易理解。鏈接:上篇:http://www.cnblogs.com/keepfool/p/5625583.html 下篇:http://www.cnblogs.com/keepfool/p/5637834.html
以下是我學(xué)習(xí)鏈接所對(duì)應(yīng)的這兩篇文章的學(xué)習(xí)摘要。
1.組件的創(chuàng)建和注冊(cè)
1.1 創(chuàng)建組件構(gòu)造器(使用Vue.extend({模板}))
var child = Vue.extend({
template:'<div>This is my first component!</div>'
})
1.2 注冊(cè)組件:Vue.component({'組件名',組件構(gòu)造器名})
Vue.component('my-component',myComponent)
1.3 使用組件
new Vue({
el:'#app'
});
<div id="app">//組件需掛載到對(duì)應(yīng)的vue實(shí)例的掛載范圍內(nèi)
<my-component></my-component>
</div>
1.4 全局注冊(cè)
eg:
<div id="example">
<my-component></my-component>
</div>
<script>
//注冊(cè),這種是全局注冊(cè)
Vue.component('my-component',{
template:'<div>A component!</div>'
})
//創(chuàng)建根實(shí)例
new Vue({
el:'#example'
})
</script>
渲染為:
<div id="example">
<div>A component!</div>
</div>
1.5 局部注冊(cè)
eg:
<div id="example">
<my-component></my-component>
</div>
<script>
var myComponent = Vue.extend( {
template: '<div>A component!</div>'
})
new Vue({
el:'#example',
components: {
'my-component':myComponent//用實(shí)例選項(xiàng)“components”注冊(cè),局部注冊(cè)
}
})
</script>
1.3 全局注冊(cè)和局部注冊(cè)區(qū)分
在new Vue ()中注冊(cè)的為局部注冊(cè),只能掛到id值與new Vue()中的el值相同的Vue實(shí)例,而在new Vue外注冊(cè)的為全局注冊(cè)的,可以掛到各個(gè)Vue實(shí)例。
eg:
<div id="example">
<my-component></my-component>
</div>
<div id="example-2">
<my-component></my-component>//將局部注冊(cè)的組件掛到不對(duì)應(yīng)的組件上,無(wú)法正確顯示
</div>
<script>
var child = {
template: '<div>A component!</div>'
}
new Vue({
el:'#example',
components: {
'my-component':child//局部注冊(cè)的組件
}
})
</script>
eg:
<div id="example">
<my-component></my-component>
</div>
<div id="example-2">
<my-component></my-component>//將全局注冊(cè)的組件掛到不同id值的組件上
</div>
<script>
//全局注冊(cè)
Vue.component('my-component',{
template:'<div>A component!</div>'
})
//創(chuàng)建根實(shí)例
var vm1 = new Vue({
el:'#example'
})
var vm2 = new Vue({
el:'#example-2'
})
</script>
2.父組件和子組件
在一個(gè)組件的模板(template)中使用了其他組件,這兩個(gè)組件之間就構(gòu)成了父子關(guān)系,該組件是父組件,父組件的模板中的組件是子組件。
子組件只能在父組件的template中使用。
- 創(chuàng)建父組件構(gòu)造器
- 創(chuàng)建子組件構(gòu)造器
- 注冊(cè)父組件
- 注冊(cè)子組件
- 使用組件
<div id="app">
<parent-component>
</parent-component>
</div>
<script>
//創(chuàng)建父組件構(gòu)造器,模板中使用了子組件<child-component></child-component>
var parent = Vue.extend({
template:'<div>This is a parent component!and <child-component></child-component></div>'
})
//創(chuàng)建子組件構(gòu)造器
var child = Vue.extend({
template:'<div>This is a child component!</div>'
})
//注冊(cè)父組件和子組件
Vue.component('child-component',child)
Vue.component('parent-component',parent)
//vue實(shí)例
new Vue({
el:'#app'
});
</script>
3.組件注冊(cè)語(yǔ)法糖:Vue.js簡(jiǎn)化組件注冊(cè)的過(guò)程
3.1 使用Vue.component()直接創(chuàng)建和注冊(cè)組件:
// 全局注冊(cè),my-component1是標(biāo)簽名稱
Vue.component('my-component1',{
template: '<div>This is the first component!</div>'
})
var vm1 = new Vue({
el: '#app1'
})
使用這種方式,Vue在背后會(huì)自動(dòng)地調(diào)用Vue.extend()。
3.2 在選項(xiàng)對(duì)象的components屬性中實(shí)現(xiàn)局部注冊(cè):
var vm2 = new Vue({
el: '#app2',
components: {
// 局部注冊(cè),my-component2是標(biāo)簽名稱
'my-component2': {
template: '<div>This is the second component!</div>'
},
// 局部注冊(cè),my-component3是標(biāo)簽名稱
'my-component3': {
template: '<div>This is the third component!</div>'
}
}
})
4. 使用script或template標(biāo)簽:分離js代碼template中的HTML元素
4.1 使用<script>標(biāo)簽
將原本寫在template的內(nèi)容寫在<script type="text/x-template" id="myComponent"></script>標(biāo)簽中,而組件的template的值為<script>標(biāo)簽的“id”值。
Vue.js根據(jù)template里面的id值,找到對(duì)應(yīng)的<script>標(biāo)簽,將標(biāo)簽中的HTML作為模板進(jìn)行編譯。
注意:使用<script>標(biāo)簽時(shí),type指定為text/x-template,意在告訴瀏覽器這不是一段js腳本,瀏覽器在解析HTML文檔時(shí)會(huì)忽略<script>標(biāo)簽內(nèi)定義的內(nèi)容。
<div id="app">
<my-component></my-component>
</div>
<script type="text/x-template" id="myComponent">
<div>This is a component!</div>
</script>
<script>
Vue.component('my-component',{
template: '#myComponent'
})
new Vue({
el: '#app'
})
</script>
4.2 使用<template>標(biāo)簽
<template id="template選項(xiàng)的值">
//這里是原來(lái)寫在template選項(xiàng)中的HTML
</template>
<div id="app">
<my-component></my-component>
</div>
<template id="myComponent">
<div>This is a component!</div>
</template>
<script>
Vue.component('my-component',{
template: '#myComponent'
})
new Vue({
el: '#app'
})
</script>
建議使用<script>或<template>標(biāo)簽來(lái)定義組件的HTML模板。
這使得HTML代碼和JavaScript代碼是分離的,便于閱讀和維護(hù)。
5. 組件的el和data選項(xiàng)
Vue.extend() 或Vue.component()中的data 和el必須是函數(shù)。
eg:
Vue.component('my-component', {
data: function(){
return {a : 1}
}
})
6.使用props
6.1基礎(chǔ)示例
var vm = new Vue({
el: '#app',
data: {
name: 'keepfool',
age: 28
},
components: {
'my-component': {
template: '#myComponent',
props: ['myName', 'myAge']
}
}
})
這個(gè)vue實(shí)例可以看作'my-component'組件的父組件。要使用父組件的數(shù)據(jù)例如'data'就要先在子組件中定義props屬性。在定義屬性的時(shí)候用的是駝峰命名。在使用組件時(shí)引用props屬性的內(nèi)容時(shí)需要轉(zhuǎn)為 kebab-case(短橫線隔開(kāi))命名。
將父組件數(shù)據(jù)通過(guò)已定義好的props屬性傳遞給子組件:
<div id="app">
<my-component v-bind:my-name="name" v-bind:my-age="age"></my-component>
//"my-name"對(duì)應(yīng)props的"myName","name"對(duì)應(yīng)父組件的數(shù)據(jù)"name","my-age"對(duì)應(yīng)props的"myAge","age"對(duì)應(yīng)父組件的數(shù)據(jù)"age"
</div>
定義子組件的HTML模板:
<template id="myComponent">
<table>
<tr>
<th colspan="2">
子組件數(shù)據(jù)
</th>
</tr>
<tr>
<td>my name</td>
<td>{{ myName }}</td>//在props屬性中定義,將父組件對(duì)應(yīng)的數(shù)值傳遞過(guò)來(lái)
</tr>
<tr>
<td>my age</td>
<td>{{ myAge }}</td>////在props屬性中定義,將父組件對(duì)應(yīng)的數(shù)值傳遞過(guò)來(lái)
</tr>
</table>
</template>
加上自定義的CSS樣式,最終效果圖如下:
在父組件中使用子組件時(shí),通過(guò)以下語(yǔ)法將數(shù)據(jù)傳遞給子組件:
<child-component v-bind:子組件prop="父組件數(shù)據(jù)屬性"></child-component>
6.2 props的綁定類型
6.2.1 單向綁定
- 修改父組件的數(shù)據(jù)會(huì)影響子組件的數(shù)據(jù);
- 修改子組件的數(shù)據(jù)不會(huì)影響父組件的數(shù)據(jù)。
6.2.2 雙向綁定
可以在使用子組件時(shí),使用.sync顯式地指定雙向綁定,這使得子組件的數(shù)據(jù)修改會(huì)回傳給父組件。
<child-component v-bind:my-name.sync="name" v-bind:my-age.sync="age"></child-component>
6.2.3 單次綁定
可以使用.once顯式地指定單次綁定,單次綁定在建立之后不會(huì)同步之后的變化,這意味著即使父組件修改了數(shù)據(jù),也不會(huì)傳導(dǎo)給子組件。
<child-component v-bind:my-name.once="name" v-bind:my-age.once="age"></child-component>
6.3 props驗(yàn)證
props: {
data: Array,
columns: Array,
filterKey: String
}
這段代碼表示:父組件傳遞過(guò)來(lái)的data和columns必須是Array類型,filterKey必須是字符串類型。
7. 解決IE不支持<template>標(biāo)簽
IE不支持<template>標(biāo)簽,所以<template>標(biāo)簽中的內(nèi)容在IE瀏覽器中會(huì)被顯示出來(lái),所以要將<template>的display設(shè)置為none。
template{
display: none;
}
8. 使用slot:內(nèi)容分發(fā)
8.1 單個(gè)slot
<div id="app">
<my-component>
<h1>Hello vue.js!</h1>
</my-component>
<my-component></my-component>
</div>
<template id="temp">
<h2>this is a component!</h2>
<slot>slot</slot>
</template>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
components:{
'my-component':{
template:'#temp',
}
}
})
</script>
<template>標(biāo)簽中的<slot>,如果在使用該組件的時(shí)候,組件中包含了其他內(nèi)容,就會(huì)替換掉<slot>的內(nèi)容,如果組件沒(méi)有包含其他內(nèi)容,<slot>中的內(nèi)容就會(huì)直接顯示。組件中包含的內(nèi)容叫做分發(fā)的內(nèi)容。
8.2 多個(gè)slot:指定名字,對(duì)應(yīng)slot
<div id="app">
<my-component>
<div slot="slot1">
<h1>Hello slot1!</h1>
</div>
<div slot="slot2">
<h1>Hello slot2!</h1>
</div>
<div slot="slot3">
<h1>Hello slot3!</h1>
</div>
</my-component>
<my-component></my-component>
</div>
<template id="temp">
<h2>this is a component!</h2>
<slot name="slot1">slot1</slot>
<slot name="slot2">slot2</slot>
<slot name="slot3">slot3</slot>
</template>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
components:{
'my-component':{
template:'#temp',
}
}
})
</script>
9.父子組件之間的訪問(wèn)
9.1父組件訪問(wèn)子組件
9.1.1 $children
父組件.$children[i]
9.1.2 $refs
在子組件上使用v-ref指令,可以給子組件指定一個(gè)索引ID:
<template id="parent-component">
<child-component1 v-ref:cc1></child-component1>
<child-component2 v-ref:cc2></child-component2>
<button v-on:click="showChildComponentData">顯示子組件的數(shù)據(jù)</button>
</template>
在父組件中,則通過(guò)$refs.索引ID訪問(wèn)子組件的實(shí)例:
showChildComponentData: function() {
alert(this.$refs.cc1.msg);
alert(this.$refs.cc2.msg);
}
9.2 子組件訪問(wèn)父組件
alert(子組件.$parent.msg)
10.自定義事件
10.1 派發(fā)事件$dispatch()
<div id="app">
<p>Messages: {{ messages | json }}</p>
<child-component></child-component>
</div>
<template id="child-component">
<input v-model="msg" />
<button v-on:click="notify">Dispatch Event</button>
</template>
<script src="js/vue.js"></script>
<script>
// 注冊(cè)子組件
Vue.component('child-component', {
template: '#child-component',
data: function() {
return {
msg: ''
}
},
methods: {
notify: function() {
if (this.msg.trim()) {
this.$dispatch('child-msg', this.msg)
this.msg = ''
}
}
}
})
// 初始化父組件
new Vue({
el: '#app',
data: {
messages: []
},
events: {
'child-msg': function(msg) {
this.messages.push(msg)
}
}
})
</script>
- 子組件的button元素綁定了click事件,該事件指向notify方法
- 子組件的notify方法在處理時(shí),調(diào)用了$dispatch,將事件派發(fā)到父組件的child-msg事件,并給該該事件提供了一個(gè)msg參數(shù)
- 父組件的events選項(xiàng)中定義了child-msg事件,父組件接收到子組件的派發(fā)后,調(diào)用child-msg事件。