用event bus解决vue中无法监听到this.$slots.default变化 (包含去除$slots.default中的空白节点
this.$slots.default
vue官网中提到:
default property 包括了所有没有被包含在具名插槽中的节点。
也就是说可以通过$slots.default
获取到通过<slot></slot>
接收到的所有对象。
但是在用的时候我发现通过$slots.default
打印出来的对象有时候会多n-1个空白节点:如下图,其实这里我只在<slot></slot>
处传入了3个节点,但打印出来却有5个。
下面是我去除空白节点的代码节选,完整代码在最后
// Tab.js -- 这是外层组件
let allSlots = this.$slots.default
this.tabSlots = allSlots.filter(item => { // 这里是用来去除$slots.default中的空节点
if(item.tag) {
return item
}else return
})
关于event bus
event bus 是一个vue实例, 这个实例可以通过emit事件并监听这个事件的方式在兄弟component或不相干的两个component之间直接进行数据传递。具体使用如下:
在main.js
中进行声明 :export const bus = new Vue();
(这里要注意记得export
哦,因为待会我们要在组件里对bus进行import
才可以用。)
代码实现
以我自己写的一个标签页组件为例:(注意示例中把css都省略了)
可以去GitHub下载项目本地运行一下,这样会更容易理解一些哦。
在
main.js
中声明一个名为bus的vue实例,在子组件中import
,通过监听需要的事件,触发bus.$emit('newchange')
方法,bus.$on('newchange', this.handleChange)
监听到'newchange'
发生,会立马触发this.handleChange
方法。具体请看代码:
// EventBusDemo.vue --这是demo页面
<Tab>
<TabItem tab-title='title1'><div class="tab_body">this is tab body.</div></TabItem>
<TabItem tab-title='title2'><div class="tab_body">this is tab body.</div></TabItem>
</Tab>
以下是bus的配置和使用
// main.js
export const bus = new Vue(); // 声明一个名为bus的vue实例
// TabItem.js--这是内层组件
<template>
<div class="tab_content">
<slot></slot> // 这里的slot与此次的bus无关,只是用于接收自定义tab内容
</div>
</template>
<script>
import { bus } from '../../main'
export default {
name: 'TabItem',
props: {
tabTitle: String
},
data() {
return{
totalTabs: ''
}
},
updated() {
this.totalTabs = this.$parent.$children.length // 获取到页面中一共传入几个TabItem
},
watch: {
totalTabs() {
bus.$emit('slot-changes') // 只要html的Tab中传入的TabItem发生变化,就会触发‘slot-changes’方法
}
}
}
</script>
// Tab.js -- 这是外层组件
<template>
<div class="tab_container">
<ul class="tab_head"><li v-for="(title, index) in tabTitle" :key='index'>{{title}}</li></ul>
<slot></slot> <!-- slot接收从TabItem中传入的tab内容 -->
</div>
</template>
<script>
import { bus } from '../../main'
export default {
name: 'Tab',
data() {
return{
tabSlots: [],
tabTitle: []
}
},
created() {
bus.$on('slot-changes', this.getTabTitle); // 监听‘slot-changes’一旦被触发,就会调用this.getTabTitle方法
},
mounted() {
this.getTabTitle();
},
methods: {
getTabTitle() {
// 获取传入tab的标签名
let allSlots = this.$slots.default
this.tabSlots = allSlots.filter(item => { // 这里是用来去除$slots.default中的空节点
if(item.tag) {
return item
}else return
})
this.tabTitle = this.tabSlots.map((tab, index) => {
return this.tabSlots[index].componentOptions.propsData.tabTitle
})
// 获取传入tab的标签名 end
}
}
}
</script>
如果有帮到你,可以的话请帮忙去github给我一颗小星星哦。么么哒~
GitHub地址