您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax | jQuery | 小程序 |

vue3递归组件封装的全过程记录

51自学网 2022-02-21 13:40:58
  javascript

前言

今天在写项目时,遇到一个自定义右键菜单的需求。在菜单中还有子菜单,所以这个时候就要用到递归组件了。所以写下这篇文章来记录一下自己编写递归组件的过程。

1、递归组件

   递归组件,顾名思义就是在组件本身内部调用自身。所以我们先构建一个组件,并在自身内部调用自身。常见的递归组件就是我们项目中经常会用到的树组件了。下面就是我自己实现的一个能够满足项目需求的递归组件的源码。

<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"  />           <!-- 判断是否需要调用自身 -->           <div v-if="item.children&&childrenMenuIndex===index"            class="context-menu context-menu_children"           >            <!-- 在组件自身内部调用自身 -->            <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}){    	//点击事件        const handleClick=(event,{text,callBack})=>{            emit('hideContextMenu');            //callBack是你自己传进来的回调函数,如果传入了,则调用自定义回调函数            if(callBack){                callBack();                return;            }        }        const hideContextMenuEvent=()=>{            emit('hideContextMenu');            }        //用于标识当前选中的菜单项        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>

注意事项

  • 在递归组件本身内部,调用自身时,需要将在递归组件上接收自己通过emit发出的自定义事件,接收后,在组件内部再次通过emit触发自定义事件。
  • 通过监听click事件,可以通过emit触发自定义事件,在组件外部监听;也可以直接在通过 props传递数据到组件内部时,就自己先构建好回调,这样就可以不用通过emit触发自定义事件了。
  • 在点击递归组件中的菜单项时,需要让递归组件销毁。所有我们需要在 递归组件内通过事件冒泡 监听click,contextmenu等事件来让组件销毁,然后通过emit触发自定义事件,让外界接收,从而达到销毁组件的目的。
  • 在递归组件内部调用click事件时,需要阻止事件冒泡以及默认事件。可以在click事件后面添加click.prevent.stop来阻止事件冒泡和默认事件。

2、右键菜单组件

  我项目中使用的是组件的形式来实现右键菜单菜单的。当然也可以通过插件的形式来实现。我这里的右键菜单本质上就是对递归组件 的二次封装,其实不用二次封装也可以,可以直接使用递归组件作为右键菜单。

<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>

注意事项

在项目中调用右键菜单时,需要先禁用掉window自身的右键菜单事件。然后实现自己的自定义菜单事件。实现代码如下所示。

const showContextMenu=(event)=>{    //禁用默认事件和阻止冒泡    event.stopPropagation();    event.preventDefault();    state.showContextMenu=true;    state.styleObj={      left:event.clientX+ "px",      top:event.clientY+'px'    }  }  //监听window自身的右键菜单事件  onMounted(()=>{    window.addEventListener('contextmenu',showContextMenu)  })  onBeforeUnmount(()=>{    window.removeEventListener('contextmenu',showContextMenu)  })

总结

到此这篇关于vue3递归组件封装的文章就介绍到这了,更多相关vue3递归组件封装内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net!


下载地址:
vue3组件中v-model的使用以及深入讲解
vue+node+socket io实现多人互动并发布上线全流程
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。