menu组件可以借助于多插槽和递归进行渲染
多slot插槽
组件中可能遇到多个插槽的情况,可以通过插槽的name属性定义使用额外的插槽
父传子:插槽中使用的数据默认为当前实例数据,即将父组件的数据传递给了子组件
子传父:作用域插槽:将插槽对应子组件的数据传递给父组件,默认使用的为父组件数据,当子组件向上传递时,使用的为子组件的数据
<template>
<div>
<myDialog ref='dialog'>
<!--父传子-->
<template v-slot:header>header{{msg}}</template>
<!--子传父-->
<template v-slot:footer='{isShow, a}'>footer-{{isShow}}-{{a}}</template>
helloWorld
</myDialog>
<button @click='change'>点我</button>
</div>
</template>
------------------------------------------------------
<script>
import myDialog from "./my-dialog"
export default {
components: {
myDialog
},
data() {
return {msg: "hihi"}
},
methods: {
change() {
this.$refs.dialog.change();
}
}
}
</script>
// my-dialog.js
<template>
<div v-if='isShow'>
<slot name='header'></slot>
这是一个弹框
<slot name='footer' :isShow='isShow' a='a'></slot>
</div>
</template>
<script>
export default {
data() {
return {
isShow: true,
}
},
methods: {
change() {
this.isShow = !this.isShow
}
},
beforeDestroy() {
this.$bus.$off('监听事件')
}
}
</script>
menu组件
- el-menu:ul元素包裹所有的菜单元素
- el-menu-item:li元素包裹菜单子元素的标题,用于渲染没有children的菜单子元素
- el-submenu:li元素包裹菜单子元素的标题+新的ul元素,用于渲染有children的菜单子元素;根据slot的name进行区分渲染;其中新的ul元素用于包裹子元素下的children
- my-menu:
函数组件,通过render方法根据菜单数据进行递归渲染
// el-menu.vue
<template>
<ul>
<slot></slot>
</ul>
</template>
----------------------------------------------
// el-menu-item.vue
<template>
<li>
<slot></slot>
</li>
</template>
----------------------------------------------
// el-submenu.vue
<template>
<li>
<div>
<slot name='title'></slot>
</div>
<ul>
<slot name='default'></slot>
</ul>
</li>
</template>
// my-menu.js
import elMenu from './components/el-menu'
import elMenuItem from './components/el-menu-item'
import elSubmenu from './components/el-submenu'
export default {
props: {
data: {
type: Array,
default: () => ([])
}
},
render() {
let renderChidren = (data) => {
return data.map(child => {
return child.children ?
<elSubmenu>
<div slot='title'>{child.title}</div>
{renderChidren(child.children)}
</elSubmenu> :
<elMenuItem nativeOnClick={() => {
console.log('原生点击事件')
}}>{child.title}</elMenuItem>
})
}
return <elMenu>
{renderChidren(this.data)}
</elMenu>
}
}
// app.vue
<my-menu :data='data'></my-menu>
data() {
return {
data:[{
title: '根1', id: 1
}, {
title: '根2',
id: 2,
children: [{
title: '根2-1', id: 21,
children: [{
title: '根2-1-1', id: 211,
children: [{
title: '根2-1-1-1', id: 2111,
}, {
title: '根2-1-1-2', id: 2112
}]
}, {
title: '根2-1-2', id: 221
}]
}, {
title: '根2-2', id: 22
}]
}, {
title: '根3', id: 3
}, {
title: '根4', id: 4
}]
}
}
子组件如何监听父组件的$mounted事件---通过eventBus
- vue的原型上定义$bus,保证eventBus来自同一个vue实例
- 在子组件的mounted上订阅事件xx
- 在父组件的mounted上发布事件xx
// main.js
Vue.prototype.$bus = new Vue()
// 子组件
mounted(){
this.$bus.$on('监听父组件mounted', (arg) => {
console.log('父组件ok了', arg)
})
},
// 父组件
mounted(){
this.$bus.$emit('监听父组件mounted', 1)
},