vue 组件递归后$emit传值失效的问题(这里提供三个解决思路,建议使用最后一个)

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&&currenClass == index &&item.datatype !=='1'"  v-on="$listeners"  :tabData="item.children"></tab-list>

            <ul v-if="item.children&&currenClass == 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"

在这里插入图片描述
为方便大家不会在写递归组件时因为传值的问题,一直困扰,特留此文。。。。

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Vue 3中,可以通过使用`$emit`方法来实现组件之间的。与Vue 2相比,Vue 3中的`$emit`的用法是一样的。 在父组件中,可以通过在子组件使用`@deleteArticle`来监听子组件触发的事件。例如,在父组件中的模板代码可以是这样的: ``` <sy-pagination @deleteArticle="deleteArticle"></sy-pagination> ``` 然后,在父组件中定义一个`deleteArticle`方法来处理子组件触发的事件。这个方法可以通过`$emit`来数据给父组件。例如: ``` const deleteArticle = (id) => { // 处理的数据 }; ``` 在子组件中,可以通过在`setup`函数中使用`emit`来触发事件并数据给父组件。例如: ``` import { reactive } from "vue"; export default { setup(props, { emit }) { let data = reactive({}); const deleteArticle = (id) => { emit("deleteArticle", id); // 使用emit触发事件,并id数据给父组件 }; return { data, deleteArticle }; }, }; ``` 这样,当子组件调用`deleteArticle`方法并一个id参数时,父组件的`deleteArticle`方法就会被触发,并且可以获取到的id来进行相应的处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vuejs使用$emit和$on进行组件之间的的示例](https://download.csdn.net/download/weixin_38644688/13193971)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Vue3 $emit父子](https://blog.csdn.net/qq_52697994/article/details/119146513)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值