Vue3.0 implements the encapsulation of the drop-down menu

Vue3.0 implements the encapsulation of the drop-down menu

Vue3.0 has been out for a while, and it is necessary to start studying it!

Let’s first look at the effect we want to achieve

It is very common to expand the content of the menu item. How to develop it in vue3.0? Here we use the default style of bootstrap

Idea 1:

<DropDown :title="'Exit'" :list="menuLists" />

Idea 2:

<drop-down :title="'Exit'">
   <drop-dowm-item>Create a new article</drop-down-item>
   <drop-dowm-item>Edit Article</drop-down-item>
   <drop-dowm-item>Personal Information</drop-down-item>
</drop-down>

Both ideas are fine. In comparison, the second idea is clearer. When using it, you know the specific level, which is also the mode of elementUI component development.
Now let's analyze the second component development idea

DropDown.ts

<template>
  <div class="dropdown" ref="dropDownRef">
    <a
      @click.prevent="toggleOpen"
      class="btn btn-secondary dropdown-toggle"
      href="#" rel="external nofollow" 
    >
      {{ title }}
    </a>
    <div class="dropdown-menu" :style="{ display: 'block' }" v-show="isOpen">
      <slot></slot>
    </div>
  </div>
</template>

js part

<script lang="ts">
import { defineComponent, ref, onMounted, onUnmounted, watch } from "vue";
import useClickOutside from "../hooks/useClickOutside";
export default defineComponent({
  name: "DropDown",
  props: {
    title:
      type: String,
      required: true,
    },
  },

  setup(context) {
    const isOpen = ref(false);
    //vue3.0 gets the reference of the DOM object const dropDownRef = ref<null | HTMLElement>(null);
    const toggleOpen = () => {
      isOpen.value = !isOpen.value;
    };
    const handleClick = (e: MouseEvent) => {
      console.log(e.target, "e");
      if (dropDownRef.value) {
        console.log(dropDownRef.value);
        if (
        //contains determines whether the node contains the node!dropDownRef.value.contains(e.target as HTMLElement) &&
          isOpen.value
        ) {
          isOpen.value = false;
        }
      }
    };
    onMounted(() => {
    //Register global click event document.addEventListener("click", handleClick);
    });
    onUnmounted(() => {
    //Unbind document.removeEventListener("click", handleClick);
    }); 
    return {
      isOpen,
      toggleOpen,
      dropDownRef,
    };
  },
});
</script>

DropDownItem.ts

<template>
  <li class="dropdowm-option" :class="{ 'is-disabled': disabled }">
    <slot></slot>
  </li>
</template>
<style scoped>

/* This is where the slot needs to penetrate*/
.dropdowm-option.is-disabled >>> * {
  color: #6c757d;
  pointer-events: none;
  background-color: transparent;
}
</style>
<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  props: {
    disabled:
      type: Boolean,
      default: false,
    },
  },
  setup() {
    return {};
  },
});
</script>

At this point the component is complete. But... we can see that the event of clicking to hide the entire document is not very relevant to the entire component, so we can extract it into a hook

useClickOutside.ts

import { ref, onMounted, onUnmounted,Ref } from 'vue'
const useClickOutside = (elementRef:Ref<null | HTMLElement>) => {
    const isClickOutside = ref(false)
    const handler = (e: MouseEvent) => {
        console.log(elementRef.value);
        if (elementRef.value) {
            if (elementRef.value.contains(e.target as HTMLElement)) {
                isClickOutside.value = false
            } else {
                isClickOutside.value = true
            }
        }
    }
    onMounted(() => {
      document.addEventListener("click", handler);
    });
    onUnmounted(() => {
      document.removeEventListener("click", handler);
    });
    return isClickOutside
}

export default useClickOutside

Then rewrite our DropDown.ts component

//Delete the existing event logic<script lang="ts">
... 
 const isClickOutside = useClickOutside(dropDownRef);
    /* console.log(isClickOutside.value, "isClickOutside"); */
    //Introduce the monitoring method, when the data changes, we change the value of isOpen to false
    watch(isClickOutside, (newValue) => {
      if (isOpen.value && isClickOutside.value) {
        isOpen.value = false;
      }
    });
 ...
</script>

The same effect is achieved, and the code of the entire component is also simplified a lot!

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • Detailed explanation of vue3 cache page keep-alive and unified routing processing
  • Vue3.0 combined with bootstrap to create a multi-page application
  • Vue3+TypeScript implements a complete example of a recursive menu component
  • Detailed explanation of the difference between routing hooks in Vue2.x and Vue3.x
  • A simple example of using Vue3 routing VueRouter4
  • Vue2/vue3 routing permission management method example
  • Use of Vue3 pages, menus, and routes

<<:  Solve the problem of IDEA configuring tomcat startup error

>>:  Determine whether MySQL update will lock the table through examples

Recommend

Use pure CSS to disable the a tag in HTML without JavaScript

In fact, this problem has already popped up when I...

How to set up ssh password-free login to Linux server

Every time you log in to the test server, you alw...

How to create dynamic QML objects in JavaScript

1. Dynamically create objects There are two ways ...

A brief discussion on several specifications of JS front-end modularization

Table of contents Preface The value of front-end ...

Detailed discussion of MySQL stored procedures and stored functions

1 Stored Procedure 1.1 What is a stored procedure...

Detailed tutorial on installing phpMyAdmin on Ubuntu 18.04

We will install phpMyAdmin to work with Apache on...

Detailed analysis of the difference between Ref and Reactive in Vue3.0

Table of contents Ref and Reactive Ref Reactive T...

Example of Vue transition to achieve like animation effect

Table of contents Results at a Glance Heart Effec...

HTML table tag tutorial (23): row border color attribute BORDERCOLORDARK

In rows, dark border colors can be defined indivi...

Detailed explanation of CSS3 elastic expansion box

use Flexible boxes play a vital role in front-end...

5 ways to quickly remove the blank space of Inline-Block in HTML

The inline-block property value becomes very usef...

IDEA2020.1.2 Detailed tutorial on creating a web project and configuring Tomcat

This article is an integrated article on how to c...

A simple way to call desktop exe programs on a web page

This article mainly introduces how to call desktop...

Use iptables and firewalld tools to manage Linux firewall connection rules

Firewall A firewall is a set of rules. When a pac...

A brief description of the relationship between k8s and Docker

Recently, the project uses kubernetes (hereinafte...