SoFunction
Updated on 2025-04-05

Record the entire process of vue3 recursive component packaging

Preface

Today, when I was writing a project, I encountered a need to customize the right-click menu. There is also a submenu in the menu, so you need to use the recursive component at this time. So write this article to record the process of writing recursive components yourself.

1. Recursive components

A recursive component, as the name implies, is to call itself inside the component itself. So we first build a component and call ourselves inside ourselves. Common recursive components are tree components that are often used in our projects. The following is the source code of a recursive component that I implemented myself that can meet the needs of the project.

<template>
   <ul class="list-container">
       <li v-for="(item,index) in listData" 
            :key="index" class="list-item" 
            @="handleClick($event,item)"
            @mouseover="childrenMenuIndex=index"
            >
           <span class="list-item_span">
               {{}}
           </span>
           <CaretRightOutlined v-if=""  />
           <!-- Determine whether you need to call yourself -->
           <div v-if="&&childrenMenuIndex===index"
            class="context-menu context-menu_children"
           >
            <!-- Call itself inside the component itself -->
            <list-comp :list-data='' @hideContextMenu='hideContextMenuEvent' />
           </div>
       </li>
   </ul>
</template>
<script>
import { defineComponent, ref } from "vue";
import {CaretRightOutlined} from '@ant-design/icons-vue';
export default defineComponent({
    name:'list-comp',
    props:{
        listData:{
            type:Array,
            default:()=>[]
        }
    },
    components:{
        CaretRightOutlined
    },
    emits:[
        "hideContextMenu"
    ],
    setup(props,{emit}){
    	//Click event        const handleClick=(event,{text,callBack})=>{
            emit('hideContextMenu');
            //callBack is a callback function you pass in by yourself. If it is passed in, call the custom callback function            if(callBack){
                callBack();
                return;
            }
        }
        const hideContextMenuEvent=()=>{
            emit('hideContextMenu');    
        }
        // Used to identify the currently selected menu item        const childrenMenuIndex=ref(-1);
        const eventNames=['click','contextmenu'];
        onMounted(()=>{ 
            (eventName=>(eventName,hideContextMenuEvent))
        })
        onBeforeUnmount(()=>{
            (eventName=>(eventName,hideContextMenuEvent))
        })
        return {
            handleClick,
            childrenMenuIndex,
            hideContextMenuEvent
        }
    }
})
</script>

Things to note

  • Inside the recursive component itself, when calling itself, it is necessary to receive the custom event sent by itself through emit on the recursive component. After receiving it, the custom event is triggered again through emit inside the component.
  • By listening to the click event, you can trigger a custom event through emit and listen outside the component; you can also build a callback by yourself when passing data through props to the component inside the component, so that you don't have to trigger a custom event through emit.
  • When clicking on a menu item in a recursive component, you need to let the recursive component be destroyed. All we need to listen to click, contextmenu and other events in the recursive component to destroy the component, and then trigger custom events through emit to allow the outside world to receive them, so as to achieve the purpose of destroying the component.
  • When calling click events inside the recursive component, the event bubbles and default events need to be prevented. You can add it after the click event to prevent event bubbles and default events.

2. Right-click menu component

My project uses components to implement the right-click menu menu. Of course, it can also be implemented in the form of plug-ins. My right-click menu here is essentially a secondary encapsulation of recursive components. In fact, it is okay not to use secondary encapsulation. You can directly use recursive components as the right-click menu.

<template>
    <teleport to='body' >
        <div class="content-menu_container" :style="styleObj">
            <list-comp 
                :list-data='menuData'
                @hideContextMenu='windowClickHandler'
             />
        </div>
    </teleport>
</template>
<script>
import { defineComponent } from "vue";
import ListComp from "./"
export default defineComponent({
    name:"contextMenu",
    components:{
        ListComp
    },
    props:{
        styleObj:{
            type:Object,
            default:()=>{}
        },
        menuData:{
            type:Array,
            default:()=>[]
        }
    },
    emits:['closeContextMenu'],
    setup(props,{emit}){
        const windowClickHandler=()=>{
            emit('closeContextMenu')
        };
        return {
            windowClickHandler,
        }
    }
})
</script>

Things to note

When calling the right-click menu in the project, you need to disable the right-click menu event of the window itself. Then implement your own custom menu events. The implementation code is shown below.

const showContextMenu=(event)=&gt;{
    //Disable default events and prevent bubbles    ();
    ();
    =true;
    ={
      left:+ "px",
      top:+'px'
    }
  }
  // Listen to the right-click menu event of the window itself  onMounted(()=&gt;{
    ('contextmenu',showContextMenu)
  })
  onBeforeUnmount(()=&gt;{
    ('contextmenu',showContextMenu)
  })

Summary

This is the end of this article about vue3 recursive component encapsulation. For more related content about vue3 recursive component encapsulation, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!