1. 組件開發(fā)
在vue中,組件是最重要的組合部分,官方中定義組件為可復(fù)用的vue實(shí)例,分為全局組件和局部組件。
1.1 全局組件
使用全局組件的步驟如下:
- 調(diào)用vue.extend()創(chuàng)建一個(gè)組件構(gòu)造器,該構(gòu)造器中有一個(gè)選項(xiàng)對(duì)象的template屬性可以用來定義組件要渲染的HTML
- 使用vue.component()注冊(cè)組件,需要提供2個(gè)參數(shù):組件的標(biāo)簽和組件構(gòu)造器。vue.component()內(nèi)部會(huì)調(diào)用組件構(gòu)造器,創(chuàng)建一個(gè)組件實(shí)例
- 將組建掛載到某個(gè)vue實(shí)例下
因?yàn)榻M件是可復(fù)用的vue實(shí)例,所以它們也能接收data、computed、watch、methods以及生命周期鉤子等選項(xiàng)
<div id="demo">
<haha></haha>
</div>
<script type="text/javascript">
var red = Vue.extend({
template: "<span style='color: red;'>全局組件</span>"
});
Vue.component('haha',red);
var demo = new Vue({
el: "#demo"
})
</script>
1.2 局部組件
調(diào)用Vue.component()注冊(cè)組件時(shí),組件的注冊(cè)是全局的,這意味著該組件可以在任意Vue示例下使用。 如果不需要全局注冊(cè),或者是讓組件使用在其它組件內(nèi),可以用選項(xiàng)對(duì)象的components屬性實(shí)現(xiàn)局部注冊(cè)。
<div id="demo">
<haha></haha>
</div>
<script type="text/javascript">
var red = Vue.extend({
template: "<span style='color: red;'>局部組件</span>"
});
var demo = new Vue({
el: "#demo",
components:{
haha:red
}
})
</script>
雖然上面的組件是在某個(gè)具體的vue實(shí)例下注冊(cè)的,但是組件構(gòu)造器還是全局的,這個(gè)并不是完全意義上的局部組件,下面這種組件才是真正意義上的局部組件。
<div id="demo">
<haha></haha>
</div>
<script type="text/javascript">
var demo = new Vue({
el: "#demo",
components:{
haha:{
template:'<span style="color: red;">局部組件</span>'
}
}
})
</script>
1.3 組件模板
可以通過<template>標(biāo)記聲明組件,再通過全局或局部注冊(cè)組件來使用。
組件中data不是屬性,是方法,需要將數(shù)據(jù)通過返回值進(jìn)行返回
<div id="demo">
<haha></haha>
</div>
<template id="abc">
<div @click="test1" style="cursor: pointer;">{{message}}</div>
</template>
<script type="text/javascript">
var demo = new Vue({
el: "#demo",
components:{
haha:{
data(){
return {
message: 'init info'
}
},
methods:{
test1(){
if(this.message == 'init info'){
this.message = 'click info'
}else{
this.message = 'init info'
}
}
},
template:"#abc"
}
}
})
</script>
2. 組件通信
2.1 父子組件
當(dāng)繼續(xù)在組件中寫組件,形成組件嵌套的時(shí)候,就是所謂的父子組件。
<div id="demo">
<haha></haha>
</div>
<template id="haha">
<div>
<h2>{{message}}</h2>
<xixi></xixi>
</div>
</template>
<template id="xixi">
<div>
<h3>{{info}}</h3>
</div>
</template>
<script type="text/javascript">
var demo = new Vue({
el: "#demo",
components:{
haha:{
data(){
return {
message: '父組件'
}
},
template:"#haha",
components:{
xixi:{
data(){
return {
info:'子組件'
}
},
template: "#xixi"
}
}
}
}
})
</script>
2.2 子組件獲取父組件的數(shù)據(jù)
在vue中,組件實(shí)例的作用域是孤立的,默認(rèn)情況下,父子組件的數(shù)據(jù)是不能共享的,也就是說,子組件是不能直接訪問父組件的數(shù)據(jù)的。為此,vue給我們提供了一個(gè)數(shù)據(jù)傳遞的選項(xiàng)prop,用來將父組件的數(shù)據(jù)傳遞給子組件。
- 父組件template中,調(diào)用子組件位置通過
:msg="message"表示將父組件中的data:message傳遞給子組件,名字為msg - 子組件components中通過props聲明['msg']表示接收父組件推送的數(shù)據(jù),子組件template直接{{msg}}進(jìn)行調(diào)用
<div id="demo">
<haha></haha>
</div>
<template id="haha">
<div>
<h2>{{message}}</h2>
<xixi :msg="message"></xixi>
</div>
</template>
<template id="xixi">
<div>
<h3>{{info}} -> {{msg}}</h3>
</div>
</template>
<script type="text/javascript">
var demo = new Vue({
el: "#demo",
components:{
haha:{
data(){
return {
message: '父組件'
}
},
template:"#haha",
components:{
xixi:{
data(){
return {
info:'子組件'
}
},
props:['msg'],
template: "#xixi"
}
}
}
}
})
</script>
2.3 父組件獲取子組件的數(shù)據(jù)
父組件獲取子組件需要子組件事件驅(qū)動(dòng),通過觸發(fā)一個(gè)事件將自身的數(shù)據(jù)發(fā)送給父組件。
步驟:
1.在子組件的methods中編寫send方法,其中通過emit函數(shù)將需要傳遞的數(shù)據(jù)綁定一個(gè)名字“child-msg”
2.在父組件的template中調(diào)用子組件的標(biāo)記處,通過@child-msg指向父組件的綁定函數(shù)"getMsg"
3.在父組件的methods中編寫getMsg函數(shù),通過方法參數(shù)接收傳遞過來的數(shù)據(jù),并將其賦值給某個(gè)data(cmsg)
4.通過使用cmsg來使用子組件的數(shù)據(jù)。
<div id="demo">
<haha></haha>
</div>
<template id="haha">
<div>
<h2>{{message}}</h2>
<xixi :msg="message" @child-msg="getMsg"></xixi>
<div>{{cmsg}}</div>
</div>
</template>
<template id="xixi">
<div @click="send">
<h3>{{info}} -> {{msg}}</h3>
</div>
</template>
<script type="text/javascript">
var demo = new Vue({
el: "#demo",
components:{
haha:{
data(){
return {
message: '父組件',
cmsg:''
}
},
methods:{
getMsg(msg){
this.cmsg = msg;
}
},
template:"#haha",
components:{
xixi:{
data(){
return {
info:'子組件數(shù)據(jù)'
}
},
props:['msg'],
template: "#xixi",
methods:{
send(){
this.$emit('child-msg',this.info);
}
}
}
}
}
}
})
</script>
需要強(qiáng)調(diào)的是,父子組件數(shù)據(jù)時(shí)單向更新的
- 當(dāng)父組件數(shù)據(jù)變化時(shí),子組件中的顯示會(huì)實(shí)時(shí)更新。
- 當(dāng)子組件數(shù)據(jù)變化時(shí),需要觸發(fā)事件來驅(qū)動(dòng)父組件數(shù)據(jù)更新。
2.4 $children和$ref
當(dāng)一個(gè)父組件中存在多個(gè)子組件時(shí),可以通過$children來訪問其下所有子組件,它會(huì)返回一個(gè)包含所有子組件的數(shù)組
<div id="count">
<button @click="showmsg">
顯示兩個(gè)組件的信息
</button>
<child1></child1>
<child2></child2>
</div>
<template id="child1">
<div>
{{ msg }}
</div>
</template>
<template id="child2">
<div>
{{ msg }}
</div>
</template>
<script>
Vue.component('child1', {
template: '#child1',
data () {
return {
msg: '這是子組件1的信息'
}
}
})
Vue.component('child2', {
template: '#child2',
data () {
return {
msg: '這是子組件2的信息'
}
}
})
new Vue({
el: '#count',
data: {
},
methods: {
showmsg () {
for(var i = 0; i < this.$children.length; i++) {
alert(this.$children[i].msg)
}
}
}
})
</script>
有時(shí)候組件過多的話,就很記清各個(gè)組件的順序與位置,所以通過給子組件一個(gè)索引ID來進(jìn)行快速定位
<div id="count">
<button @click="showmsg">
顯示兩個(gè)組件的信息
</button>
<child1 ref='c1'></child1>
<child2 ref='c2'></child2>
</div>
<template id="child1">
<div>
{{ msg }}
</div>
</template>
<template id="child2">
<div>
{{ msg }}
</div>
</template>
<script>
Vue.component('child1', {
template: '#child1',
data () {
return {
msg: '這是子組件1的信息'
}
}
})
Vue.component('child2', {
template: '#child2',
data () {
return {
msg: '這是子組件2的信息'
}
}
})
new Vue({
el: '#count',
data: {
},
methods: {
showmsg () {
alert(this.$refs.c1.msg)
alert(this.$refs.c2.msg)
}
}
})
</script>
2.5 $parent和$root
子組件通過訪問$parent獲得其父組件的實(shí)例對(duì)象
<div id="count">
父組件中的msg: {{ msg }}
<child1 ref='c1'></child1>
<child2 ref='c2'></child2>
</div>
<template id="child1">
<div>
{{ msg }}
<button @click="showpmsg">
顯示父組件msg
</button>
</div>
</template>
<template id="child2">
<div>
{{ msg }}
</div>
</template>
<script>
Vue.component('child1', {
template: '#child1',
data () {
return {
msg: '這是子組件1的信息'
}
},
methods: {
showpmsg () {
alert(this.$parent.msg)
}
}
})
Vue.component('child2', {
template: '#child2',
data () {
return {
msg: '這是子組件2的信息'
}
}
})
new Vue({
el: '#count',
data: {
msg: 'hello parent'
}
})
</script>
子組件訪問根組件 $root 當(dāng)前組件樹的根 Vue 實(shí)例。如果當(dāng)前實(shí)例沒有父實(shí)例,此實(shí)例將會(huì)是其自已。
<div id="count">
父組件中的msg: {{ msg }}
<child1 ref='c1'></child1>
<child2 ref='c2'></child2>
</div>
<template id="child1">
<div>
{{ msg }}
<cchild></cchild>
</div>
</template>
<template id="child2">
<div>
{{ msg }}
</div>
</template>
<template id="cchild">
<div>
<button @click="showroot">
showrootmsg
</button>
</div>
</template>
<script>
Vue.component('child1', {
template: '#child1',
data () {
return {
msg: '這是子組件1的信息'
}
},
methods: {
showpmsg () {
alert(this.$parent.msg)
}
}
})
Vue.component('child2', {
template: '#child2',
data () {
return {
msg: '這是子組件2的信息'
}
}
})
Vue.component('cchild', {
template: '#cchild',
data () {
return {
msg: '這是子組件1的信息'
}
},
methods: {
showroot () {
alert(this.$root.msg)
}
}
})
new Vue({
el: '#count',
data: {
msg: 'hello root'
}
})
</script>