组件通信
自定义事件
Vue有一套与JS观察者模式类似的设计,子组件用$emit()来触发事件,父组件用$on()来监听子组件的事件。
<div id='app'>
<son-component @change='handleTotal'></son-component>
<!--change就是自定义事件-->
</div>
Vue.component('son-component',{
template:
'<div>\
<button @click='handleIncrease'>+1</button>\
<button @click='handleReduce'>-1</button>\
</div>',
data:function(){
return {
count: 0
}
},
methods:{
handleIncrease:function(){
this.count += 1;
this.$emit('change',this.count)
},
handleReduce:function(){
this.count -= 1;
this.$emit('change',this.count)
}
}
})
var app = new Vue({
el:'#app',
data:{
total: 0
},
methods:{
handleTotal:function(value){
this.total = value
}
}
})
在组件中使用v-model
<div id="app">
<son-component v-model='total'></son-component>
</div>
Vue.component('son-component',{
template:'<div>\
<button @click="handleIncrease">+1</button>\
</div>',
methods:{
handleIncrease:function(){
this.count +=1
this.$emit('input',this.count)
}
},
data:function(){
return {
count:1
}
}
})
var app = new Vue({
el:'#app',
data:{
total: 1
}
})
非父组件的通信
<div id="app">
<component-a ref='a'></component-a>
<component-b ref='b'></component-b>
<hr style="background-color:cyan;height:4px;">
<component-c ref='c'></component-c>{{msg}}
<button @click='getChildData'>我是父组件的按钮,我要拿到子组件的内容</button>
{{formChild}}
</div>
Vue.component('component-a', {
template: '<div><button @click="handle">我是a组件的按钮</button></div>',
data: function () {
return {
a: '其实我是a组件的data定义的内容,我通过b中的函数显示出来。',
msg: '我是a中的msg'
}
},
methods: {
handle: function () {
this.$root.bus.$emit('eve', this.a) //eve为自定义的事件名,this.a是要传送的数据
}
}
})
Vue.component('component-b', {
template: '<div>其实我是B组件</div>',
data: function () {
return {
msg: '我是b中的msg'
}
},
created: function () {
this.$root.bus.$on('eve', function (value) {
alert(value)
})
}
})
Vue.component('component-c', {
template: '<button @click="amend">点我修改父组件的内容</button>',
data: function () {
return {
msg: '我是c中的msg'
}
},
methods: {
amend: function () {
this.$parent.msg = '猪突猛进'
}
}
})
var app = new Vue({
el: '#app',
data: {
bus: new Vue(),
msg: '我是未修改过的父组件的内容',
formChild: '还未拿到'
},
methods: {
//用来拿子组件中的内容
getChildData: function () {
this.formChild = this.$refs.b.msg;
}
}
})
插槽
单个slot
<div id="app">
<part-component>
{{msg}}
</part-component>
</div>
var app = new Vue({
el:"#app",
data:{
msg:'我爱你'
},
components:{
"part-component":{
template:'\
<div>你爱我吗?\
<slot>你要是不爱我我就出来再问你一遍。</slot>\
</div>'
}
}
})
使用{{msg}}渲染时:

<slot>标签中的内容:

具名插槽
<div id="app">
<part-component>
<h1 slot='head'>1</h1>
<h2>2</h2>
<h3>3</h3>
</part-component>
</div>
var app = new Vue({
el: "#app",
data: {
},
components: {
"part-component": {
template: '\
<div>\
<div class="head">\
<slot name="head"></slot>\
</div>\
<div class="container">\
<slot></slot>\
</div>\
</div>',
}
}
})
template中<slot>标签中定义的name值会自动匹配html标签中slot属性值相同的属性;template中未定义name值的<slot>标签会去匹配没有设置slot属性的标签,从而改变其dom结构。从而更新数据变得方便。
作用域插槽
作用是通过slot从子组件获取数据。
<div id="app">
<my-component>
<template slot='name' slot-scope="variable">
<!-- variable是一个临时变量名 -->
{{variable}}
<!--渲染出的标签属性可以以{{variable.xx}}方式渲染到html-->
</template>
</my-component>
</div>
Vue.component('my-component',{
template:'\
<div>\
<slot class="hh" id="qq" qwe="123" text="我是要被拿到的数据" name="name"></slot>\
</div>'
})
var app = new Vue({
el:'#app',
data:{
}
})
访问slot插槽
Vue.component('name-component', {
template: '<div>\
<div class="header"> \
<slot name="header"></slot> \
</div> \
<div class="container"> \
<slot></slot> \
</div> \
<div class="footer"> \
<slot name="footer"></slot> \
</div> \
</div>',
mounted: function () {
var head = this.$slots.header;
console.log(head[0].elm.innerHTML) //这样便能获取到插槽类名为header的内容
}
})
动态组件
<div id="app">
<component :is='thisView'></component>
<button @click="dispose('a')">1</button>
<button @click="dispose('b')">2</button>
<button @click="dispose('c')">3</button>
<button @click="dispose('d')">4</button>
</div>
Vue.component('component-a',{
template:'<div>哈哈</div>'
})
Vue.component('component-b',{
template:'<div>嘿嘿</div>'
})
Vue.component('component-c',{
template:'<div>嗯嗯</div>'
})
Vue.component('component-d',{
template:'<div>啵啵</div>'
})
var app = new Vue({
el:'#app',
data:{
thisView:'component-a'
},
methods:{
dispose:function(tag){
this.thisView = 'component-' + tag;
}
}
})
