组件通讯-非父子,slot插槽
组件通讯-非父子
非父子组件之间通过一个空的Vue实例来传递数据。
1 2 3 4 5
| 组件A给组件B传值: 1. 创建一个bus对象 2. 组件a触发事件,给组件b发送数据 3. 组件b给bus对象注册事件 4. 组件b提供函数,用于接收数据
|
1 2 3 4 5 6 7
| <button @click="send">表白</button>
methods: { send() { bus.$emit("get", this.msg); } }
|
1 2 3 4 5 6 7
| created () { bus.$on("get", (msg)=>{ console.log("这是rose注册的事件", msg); this.msg = msg; }); }
|
1 2 3 4
| bus.$on("get", (msg)=>{ console.log("这是rose注册的事件", msg); this.msg = msg; });
|
注意点:1. 传递和接受数据的事件必须在同一个总线上 2. 注册的事件和触发的事件必须保持一致
bus是一种通用的组件通讯方案
现在有三种组件通讯的方案
1 2 3 4
| 1. 父传子 2. 子传父 3. 非父子(bus) 其实bus方案也适用于父传子和子传父的方案
|
slot插槽
当组件中某一项需要单独定义,那么就应该使用slot
Vue 实现了一套内容分发的 API,将 <slot>元素作为承载分发内容的出口。
匿名插槽slot
除非子组件模板包含至少一个 <slot> 插口,否则父组件的内容将会被丢弃 ,当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。
在组件的模版中定义slot插槽
1 2 3 4 5 6 7 8 9 10 11
| Vue.component("modal", { template: ` <div class="modal"> <p>温馨提示</p> <div> <slot></slot> </div> <button>关闭</button> </div> `, });
|
父组件传值
1 2 3 4
| <modal> <h3>你确定要退出系统吗?</h3> </modal> <modal>你确定要删除这个内容吗?</modal>
|
具名插槽
如果一个组件中想使用多个slot那么此时就应该使用具名插槽。
使用方法
- 给插槽添加name属性
- 给插入内容添加slot属性,属性值和插槽的name属性值相同
1 2 3 4 5 6 7 8 9
| Vue.component("modal", { template: ` <div class="modal"> <slot name="header"></slot> <slot name="content"></slot> <slot name="footer"></slot> </div> `, });
|
1 2 3 4 5 6 7 8 9 10 11
| <modal> <template v-slot:header> 温馨提示 </template> <template v-slot:content> 你要删除内容吗 </template> <template v-slot:footer> <button>关闭</button> </template> </modal>
|
作用域插槽
在分发内容时,如果需要用到子组件内的数据,需要用到作用域插槽
作用域插槽的使用
- 给插槽添加name属性和自定义属性
- 将插入内容用template标签包裹起来,给template标签添加
v-slot: 属性值="obj",属性值和插槽的name属性值相同。(template只用来分块,不会渲染,具名插槽也可以使用) - 自定义属性和属性值会自动添加到一个对象中,这个对象可以通过上面的obj取到
1 2 3 4 5 6 7 8 9
| Vue.component('modal', { template: ` <div> <h3><slot name="title"></slot></h3> <p><slot name="content"></slot></p> <slot name="confirm" value="确定"></slot> </div> ` })
|
1 2 3 4 5 6 7 8 9 10 11
| <modal> <template v-slot:title>温馨提示</template> <template v-slot:content>你确定也要退出了</template> <template v-slot:confirm="scope"> <button href="#">{{scope.value}}</button> </template> <template v-slot:cancel="scope"> <button href="#">{{scope.value}}</button> </template> </modal>
|
没有指定v-slot的内容会给匿名插槽或v-slot: default