The whole process record of vue3 recursive component encapsulation

The whole process record of vue3 recursive component encapsulation

Preface

When writing a project today, I encountered a need for a custom right-click menu. There are submenus in the menu, so recursive components are used at this time. So I wrote this article to record the process of writing recursive components.

1. Recursive components

A recursive component, as the name suggests, calls itself within the component itself. So we first build a component and call itself within itself. The common recursive component is the tree component that is often used in our projects. Below is the source code of a recursive component I implemented to meet the project requirements.

<template>
   <ul class="list-container">
       <li v-for="(item,index) in listData" 
            :key="index" class="list-item" 
            @click.prevent.stop="handleClick($event,item)"
            @mouseover="childrenMenuIndex=index"
            >
           <span class="list-item_span">
               {{item.text}}
           </span>
           <CaretRightOutlined v-if="item.children" />
           <!-- Determine whether to call itself -->
           <div v-if="item.children&&childrenMenuIndex===index"
            class="context-menu context-menu_children"
           >
            <!-- Calling the component itself -->
            <list-comp :list-data='item.children' @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 the callback function you passed in. If passed in, the custom callback function will be called 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(()=>{ 
            eventNames.forEach(eventName=>window.addEventListener(eventName,hideContextMenuEvent))
        })
        onBeforeUnmount(()=>{
            eventNames.forEach(eventName=>window.removeEventListener(eventName,hideContextMenuEvent))
        })
        return {
            handleClick,
            childrenMenuIndex,
            hideContextMenuEvent
        }
    }
})
</script>

Precautions

  • 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, trigger the custom event 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 the callback yourself when passing data to the component through props, so you don't need to trigger a custom event through emit.
  • When you click a menu item in a recursive component, you need to destroy the recursive component. All we need to do is to listen to click, contextmenu and other events through event bubbling in the recursive component to destroy the component, and then trigger the custom event through emit so that the outside world can receive it, thereby achieving the purpose of destroying the component.
  • When calling the click event inside a recursive component, you need to prevent event bubbling and the default event. You can add click.prevent.stop after the click event to prevent event bubbling and default events.

2. Right-click menu component

In my project, I use components to implement the right-click menu. Of course, it can also be implemented through plug-ins. The right-click menu here is essentially a secondary encapsulation of the recursive component. In fact, there is no need for secondary encapsulation. You can directly use the recursive component 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 "./list-comp.vue"
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>

Precautions

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

const showContextMenu=(event)=>{
    //Disable default events and prevent bubbling event.stopPropagation();
    event.preventDefault();
    state.showContextMenu=true;
    state.styleObj={
      left:event.clientX+ "px",
      top:event.clientY+'px'
    }
  }
  //Monitor the right-click menu event of the window itself onMounted(()=>{
    window.addEventListener('contextmenu',showContextMenu)
  })
  onBeforeUnmount(()=>{
    window.removeEventListener('contextmenu',showContextMenu)
  })

Summarize

This is the end of this article about vue3 recursive component encapsulation. For more relevant vue3 recursive component encapsulation content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vue3+TypeScript implements a complete example of a recursive menu component
  • Vue.js recursive component to implement tree menu (example sharing)
  • Vuejs uses recursive components to implement tree directories
  • Vue.js learning recursive components
  • Vue2 recursive component to implement tree menu
  • Learn how to use Vue3 recursive components in 10 minutes

<<:  Detailed explanation of data types and schema optimization in MySQL

>>:  Detailed steps for using jib for docker deployment in Spring Cloud

Recommend

DHCP Configuration Tutorial in CentOS7 Environment

Table of contents Configuration command steps in ...

Introduction to common MySQL storage engines and parameter setting and tuning

MyISAM, a commonly used storage engine in MySQL c...

How to install kibana tokenizer inside docker container

step: 1. Create a new docker-compose.yml file in ...

Analysis of the Linux input subsystem framework principle

Input subsystem framework The linux input subsyst...

Solution to Element-ui upload file upload restriction

question Adding the type of uploaded file in acce...

Detailed explanation of MySQL foreign key constraints

Official documentation: https://dev.mysql.com/doc...

Three methods to modify the hostname of Centos7

Method 1: hostnamectl modification Step 1 Check t...

Detailed explanation of MySQL deadlock and database and table sharding issues

Record the problem points of MySQL production. Bu...

Docker and portainer configuration methods under Linux

1. Install and use Docer CE This article takes Ce...

This article will show you how JavaScript garbage collection works

Table of contents 1. Overview 2. Memory Managemen...

Solution to 1290 error when importing file data in mysql

Error scenario Use the mysql command in cmd to ad...

Solution to occasional crash of positioning background service on Linux

Problem Description In the recent background serv...

Detailed steps to configure my.ini for mysql5.7 and above

There is no data directory, my-default.ini and my...

Detailed tutorial on deploying Apollo custom environment with docker-compose

Table of contents What is the Apollo Configuratio...

Vue uses WebSocket to simulate the chat function

The effect shows that two browsers simulate each ...