vue 组件递归后$emit传值失效的问题(这里提供三个解决思路,建议使用最后一个)
分析原因
1.首先造成传值失效的问题是组件递归后事件传递不到上层。所以造成的问题是在递归组件的第二层里面,监听不到当前事件。
出现的现象
2.造成的现象是我点击递归出来的子菜单的时候,父级组件拿不到点击获取的值,第一次点击渲染的值可以获取到
解决问题的方法
1.可以点击的时候将值存储再vuex里面 点击的时候在父级页面获取到vuex里面存储的值
弊端:点击完页面刷新后,vuex里面的值会消失,影响页面功能(非必要不选择);
2.可以通过$eventBus事件中转的方式解决(没有更好的办法可以选择)
弊端:需要建一个事件中转站,没有事件去触发。
3.可以再递归组件中监听当前事件,只需要在递归组件中添加v-on="$listeners"(最优解)
具体代码如下
父组件
<template>
<div>
<NodeTabs @tabChange="tabChange" :tabData="tabList"></NodeTabs>
</div>
</template>
<script>
import NodeTabs from "@/components/tabList"
export default {
data(){
return {
tabList:[
{
tabName:"菜单一",
ricid:"xx",
datatype:0,
children:[
{
tabName:"菜单二",
ricid:"xx"
},
{
tabName:"菜单二222222222222222222.2",
ricid:"xx"
},
{
tabName:"菜单1.3",
ricid:"xx"
}
]
},
{
tabName:"菜单二",
ricid:"xx",
datatype:'1',
children:[
{
tabName:"菜单二",
ricid:"xx"
},
{
tabName:"菜单2.2",
ricid:"xx"
},
{
tabName:"菜单2.3",
ricid:"xx"
},
{
tabName:"菜单二2.1",
ricid:"xx"
},
{
tabName:"菜单2.2",
ricid:"xx"
},
{
tabName:"菜单2.3",
ricid:"xx"
},
{
tabName:"菜单二",
ricid:"xx"
},
{
tabName:"菜单2.2",
ricid:"xx"
},
{
tabName:"菜单2.3",
ricid:"xx"
},
{
tabName:"菜单二",
ricid:"xx"
},
{
tabName:"菜单2.2",
ricid:"xx"
},
{
tabName:"菜单2.3",
ricid:"xx"
}
]
},
{
tabName:"菜单三",
ricid:"xx",
datatype:0,
children:[
{
tabName:"菜单二",
ricid:"xx"
},
{
tabName:"菜单3.2",
ricid:"xx"
},
{
tabName:"菜单3.3",
ricid:"xx"
}
]
}
],
currentNodes:{}
}
},
methods:{
tabChange(val){
console.log(val,"val_______________")
}
},
components: {NodeTabs},
}
</script>
子组件(递归组件)
<template>
<ul class="tab_ctn">
<li v-for="(item,index) in tabData" :class="currenClass == index?'active':'liStyle'" :style="item.datatype =='1'?{width:'200px'}:'auto'" @click.stop.prevent="tabChange(item,index,$event)" @mouseleave="leveTab" :key="index">
<div class="p_style">
<p :title="item.tabName">{{item.tabName}}</p>
<Icon type="ios-arrow-down" v-if="item.datatype =='1'"/>
</div>
<tab-list v-if="item.children&¤Class == index &&item.datatype !=='1'" v-on="$listeners" :tabData="item.children"></tab-list>
<ul v-if="item.children&¤Class == index&&item.datatype =='1' && tabIsow" @mouseleave="leveTab" :style="{width: width}" class="tabSelect" id="tabSelect" style="">
<li v-for="(item,indexs) in item.children" :key="indexs" @click.stop="tabChange1(item,indexs)" style="text-align: left;" :class="currenClass1 == indexs?'active':''">
<p :title="item.tabName">{{item.tabName}}</p>
</li>
</ul>
</li>
</ul>
</template>
<script>
export default {
name: "tab-list",
data(){
return{
tabIsow:true,
currenClass:0,
currenClass1:0,
currenClass2:0,
width:''
}
},
props: {
tabData:Array
},
methods: {
tabChange(item,index,e){
var that = this
this.currenClass = index;
this.tabIsow=true
that.$emit("tabChange",item)
if(item.children && item.datatype == 1){
console.log('Xiala')
}else{
// this.tabChange2(item.children[0],0);
}
this.width = e.target.parentElement.offsetWidth + 'px';
},
tabChange1(item,index){
this.currenClass1 = index;
this.tabIsow=false
this.$emit("tabChange",item)
// this.$router.push({name : item.recId});
},
tabChange2(item,index){
this.currenClass2 = index;
this.$emit("tabChange",item)
// this.$router.push({name : item.recId});
},
leveTab(){
this.tabIsow=false
},
// mouseTab(index){
// this.currenClass = index;
// this.tabIsow=true
// }
},
}
</script>
<style scoped>
ul,li{
margin: 0;
padding: 0;
list-style: none;
}
.p_style{
display: flex;
align-items: center;
justify-content: center
}
.active{
background:#ffffff !important;
color: #2d8cf0!important;
border-bottom:0!important;
border-left: 1px solid #2d8cf0!important;
border-right: 1px solid #2d8cf0!important;
border-top:1px solid #2d8cf0!important;
}
.tab_ctn{
display: flex;
align-items: center;
position: relative;
z-index: 99999;
}
.tab_ctn li p{
padding: 0 16px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tab_ctn li{
width: auto;
height: 45px;
line-height: 45px;
text-align: center;
color: #757575;
font-weight: bold;
padding: 5px 0;
background: white;
border: 1px solid black;
cursor: pointer;
border-right: none;
border-left: none;
background: #f8f9fd;
border-top: 1px solid #e6e9f1 ;
border-bottom: 1px solid #e6e9f1;
}
.tab_ctn li:last-child{
/*border: 1px solid black;*/
}
.active .tab_ctn{
position: absolute;
top: 52px;
left: 0;
}
.tabSelect{
width: auto;
position: absolute;
top: 50px;
box-shadow: 0 1px 6px rgb(0 0 0 / 20%);
max-height: 350px;
overflow: auto;
}
#tabSelect li{
border-bottom: 1px solid #e6e9f1 !important;
}
.active ul li{
border: none!important;
background: #ffffff;
border-top: 0!important;
border-bottom: 1px solid #e6e9f1 !important;
}
.active ul .active{
color: #3872ff !important;
font-weight: bold !important;
border-bottom: 2px solid #306eff !important;
}
</style>
重点就是在 递归的组件中 添加 v-on="$listeners"
为方便大家不会在写递归组件时因为传值的问题,一直困扰,特留此文。。。。