接上一篇组件与复用技术(上)
三、组件之间的通信(1):props / $emit
- 认识父组件和子组件
①父组件:在HTML中使用组件的代码被称为“父组件”。
②子组件:在JS中注册组件的代码被称为“子组件”。 - 父组件向子组件的通信:
①数据从父组件传递给子组件。
②通过props来实现。
③通过props来实现的父组件向子组件的通信是“单数据流传递”。
由于是单数据流传递,因此在子组件中不允许执行对props数据实现赋值的各种操作。
解决方案:在子组件的data区再次定义一个普通变量,让各种赋值操作针对这个普通变量来实现。
④通过props传递过来的数据作为初始值且发生了变化或者重新赋值,则可以利用计算属性或者侦听属性来解决双向绑定的问题。
⑤通过props传递给子组件的属性:
A、不能在子组件的methods方法中对props属性进行赋值。
B、不能在子组件的表单元素中利用v-model双向绑定props属性。 - 子组件向父组件的通信:
①数据从子组件传递给父组件
②通过父组件的自定义事件来实现 - 自定义事件:
触发自定义事件:this.$emit(‘自定义事件名’,参数);
例:为<my-book></my-book>
添加功能。单击“作者”,在控制台显示作者简介。
1、为父组件绑定自定义事件:
<my-book @custom=“bookCustom” intro=“作者致力于…….”></my-book>
2、在Vue实例中设置bookCustom的方法:
new Vue({
methods:{
bookCustom:function(introduce){
console.log(introduce);
}
}
})
3、在子组件中指定何时出发custom事件。
Vue.component(‘my-book’,{
template:‘<p @click=“authorClick”>’,
props:[‘intro’],
methods:{
authorClick:function(){
this.$emit(‘custom’,this.intro);
}
}
})
四、在组件中使用v-model指令:【语法糖】
- 利用v-model指令绑定变量可以解决将子组件中的计算结果传递给父组件的问题。
父组件:
<my-buttons :num=“total” v-model=“total” @input=“buttonsInput”> </my-buttons>
子组件:
Vue.component(‘my-buttons’,{……}) Vue实例: var vm=new Vue({ methods:{ buttonsInput:function(value){ this.total=value; } } })
- 利用v-model指令绑定具备表单元素的组件上。
父组件:<my-text :num=“total” v-model=“total” @input=“textInput”></my-text>
子组件:
Vue.component('my-text',{
template:`
<input type="text" :value="num" @input="textInput" />
`,
props:['num'],
methods:{
textInput:function(event){
this.$emit('input',event.target.value);
}
}
})
Vue实例:
var vm=new Vue({
el:'#app',
data:{
total:10
},
methods:{
add:function(){
this.total++;
},
sub:function(){
this.total--;
},
textInput:function(value){
this.total=value;
}
}
})
五、组件之间的通信(2):中央事件总线(bus) bus. e m i t ( ) / b u s . emit() / bus. emit()/bus.on()
1、首先创建一个空Vue实例:var bus = new Vue();
2、发送通信的那一方:bus.$emit(‘eventTypeName’,parameter)
3、接收通信的那一方:bus.$on(‘eventTypeName’,function(value){……})
接收通信的那一方一般在mounted钩子函数中对事件进行监听。
4、注意:发送发$emit()的eventTypeName必须接收方$on()的eventTypeName一致。
例1:利用中央事件总线的方式在父组件与子组件之间进行通信。
例2:利用中央事件总线的方式在兄弟组件之间进行通信。
六、组件之间的通信(3):父链
1、在子组件中引用父组件:this.$parent
2、在父组件中引用子组件:this.$children,这可以引用父组件所属的多个子组件。
所以this.$children将返回一个包含多个子组件的数组。
例:利用父链的方式完成计算总数的功能。
七、组件之间的通信(4):子组件索引
1、需要在HTML中引用组件的父组件位置利用ref属性为组件起一个名称。
<my-com ref=“comA”></my-com>
2、在Vue实例中利用下列格式引用子组件:
this.$refs.comA.子组件数据
注意:this.$refs,表示所有在主组件中有ref名称的组件的集合。
八、组件的内容分发技术:slot插槽
1、单个slot插槽:
(1)可以在组件的注册代码中,在template选项中使用<slot></slot>标记对生成一个组件插槽。
(2)在组件的使用代码中(HTML),允许在组件标记对内部输入内容插入插槽
(3)<slot></slot>标记对内部允许书写插槽默认的内容。
2、多个slot插槽:允许一个内容插入多个插槽中。
3、具名插槽:
(1)在<slot></slot>标记对中可以使用name属性指定插槽名称。
(2)在组件使用代码中,可以对任意出现在组件标记对内部的标记对使用slot属性指定slot名称。
template:`
<div>
<p>我是一个组件</p>
<slot name=“slot1”></slot>
<slot name=“slot2”></slot>
</div>
`
<my-com>
<div slot=“slot1”>123</div>
<div slot=“slot2”>abc</div>
</my-com>
例:利用slot制作一个滑动门效果。
tabs.js:用来实现滑动门的整体布局。[current属性、<slot></slot>]
panel.js:用来实现滑动门显示的内容。[title属性、<slot></slot>]
<tabs current="2">
<panel title="张三">张三的内容</panel>
<panel title="李四">李四的内容</panel>
</tabs>
4、作用域插槽:
(1)作用域插槽可以将数据从带有插槽的子组件传递给父组件。
(2)在子组件中,可以为插槽<slot></slot>设置自定义属性。
template:`
<div class=“com”>
<slot msg=“你好” abc=“1500”></slot>
</div>
`
(3)在父组件中,可以使用<template></template>设置一个可以调用子组件插槽属性
的作用域。
<my-com>
<template slot-scope=“temp”>
<p>{{temp.msg}},我的售价是{{temp.abc}}</p>
</template>
</my-com>
注意:slot-scope可以简写为scope。
(4)在插槽上设置的自定义属性可以绑定子组件的data区域的数据。
<slot :msg=“list”></slot>