Vue implements Modal component based on Teleport

Vue implements Modal component based on Teleport

1. Get to know Teleport

For example, if we write global components such as Modal components, Message components, and Loading components without Teleport, and introduce them into a .vue file, their HTML structure will be added to the component template, which is not perfect.

  • No Teleport

  • Teleport

The following is a practical introduction on how to develop Modal components using Teleport

2. Basic usage of Teleport

The writing of Teleport is very simple. You just need to wrap the content with <Teleport></Teleport> and use to specify which parent node to hang the HTML under.

<teleport to="#modal">
Contents</teleport>

3. First step optimization

If we hard-code the DOM that Teleport is to mount in the code, then every time a global component is created, a DOM node will be required, and there will be more and more of them, and they will always exist. This writing method is not very elegant. A better solution is:

  • When creating a component, dynamically create a DOM node document.createElement().
  • And add it to the body, document.body.appendChild(),
  • Destroy this dom document.body.removeChild() when the component is uninstalled.
setup(){
  const node = document.createElement('div')
  node.id = 'modal'
  document.body.appendChild(node)
  onUnmounted(() => {
    document.body.removeChild(node)
  })
}

4. Second step optimization

If we want to add Message components, Loading components and other functions in the future, we will also need to use Teleport. It is a bit redundant to write such a piece of code in each component. Vue3 enables us to easily extract the logical functions, thereby achieving the purpose of logic reuse.

We create the useDOMCreate.ts file in the src-hooks folder to encapsulate this logic

// hooks/useDOMCreate.ts
import { onUnmounted } from 'vue'

function useDOMCreate(nodeId:string):void {
  const node = document.createElement('div')
  node.id = nodeId
  document.body.appendChild(node)
  onUnmounted(() => {
    document.body.removeChild(node)
  })
}
export default useDOMCreate

use:

import useDOMCreate from '../hooks/useDOMCreate'
setup(props, ctx) {
    useDOMCreate('modal')
}

5. Implement Modal component

The details of encapsulating the Modal component will not be discussed here, and there is no complicated logic. Directly on the code.

//Modal.vue
<template>
  <teleport to="#modal">
    <div class="modal d-block" tabindex="-1" v-if="isVisible">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">{{title}}</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true" @click="onClose">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <slot></slot>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal" @click="onClose">Cancel</button>
            <button type="button" class="btn btn-primary" @click="onConfirm">Confirm</button>
          </div>
        </div>
      </div>
    </div>
  </teleport>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import useDOMCreate from '../hooks/useDOMCreate'
export default defineComponent({
  name: 'Modal',
  emits: ['model-close', 'model-confirm'],
  props: {
    title:
      type: String,
      default: ''
    },
    isVisible: {
      type: Boolean,
      default: false
    }
  },
  setup(props, ctx) {
    useDOMCreate('modal')
    const onClose = () => {
      ctx.emit('model-close')
    }
    const onConfirm = () => {
      ctx.emit('model-confirm')
    }
    return {
      onClose,
      onConfirm
    }
  }
})
</script>

Usage Examples

<template>
  <div class="post-detail-page">
    <button type="button" class="btn btn-danger" @click="handleDelete">Delete</button>
    <modal title='Are you sure to delete? ' :isVisible="modalVisible" @model-close="handleModalClose" @model-confirm="handleModalConfim">
      <p>Are you sure you want to delete this article? </p>
    </modal>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import Modal from '../components/Modal.vue'

export default defineComponent({
  name: 'post-detail',
  components: { Modal },
  setup() {
    const modalVisible = ref(false)
    const handleDelete = () => {
      modalVisible.value = true
    }
    const hanldeModalClose = () => {
      modalVisible.value = false
    }
    const handleModalConfim = () => {
      modalVisible.value = false
      ...
     //Subsequent logical processing}
    return {
      hanldeModalClose,
      handleModalConfim,
      handleDelete,
      modalVisible
    }
  }
})
</script>

The above is the details of how vue implements Modal components based on Teleport. For more information about vue Teleport implementing Modal components, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Detailed explanation of the use of Teleport in Vue3
  • Detailed explanation of how to use the vue3 Teleport instant movement function
  • Detailed explanation of the practice and principle of Vue3 Teleport
  • How to customize dialog and modal components in Vue3
  • Handwritten Vue pop-up window Modal implementation code
  • The modal component of iview in vue component has a problem: whether the modal is displayed or not should use v-show

<<:  How to reset the root password in mysql8.0.12

>>:  Implementation of the Pycharm installation tutorial on Ubuntu 18.04

Recommend

How to deploy ElasticSearch in Docker

1. What is ElasticSearch? Elasticsearch is also d...

Install MySQL 5.7.18 using rpm package under CentOS 7

I have been using MySQL recently. The article mys...

Docker and portainer configuration methods under Linux

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

The use of textarea in html and common problems and case analysis

The textarea tag is an HTML tag that we often use....

How to use LibreOffice to convert document formats under CentOS

Project requirements require some preprocessing o...

Detailed explanation of Vue save automatic formatting line break

I searched for many ways to change it online but ...

How to convert a column of comma-separated values ​​into columns in MySQL

Preface Sometimes you come across business tables...

VMware Workstation virtual machine installation operation method

Virtual machines are very convenient testing soft...

Windows system mysql5.7.18 installation graphic tutorial

MySQL installation tutorial for Windows system do...

How to introduce scss into react project

First download the dependencies yarn add sass-loa...

Detailed installation and configuration tutorial of MySQL 5.7 under Win10

1. Unzip MySQL 5.7 2. Create a new configuration ...

html opens a new window with a hyperlink and can control window properties

1. The window size opened by the HTML hyperlink C...

HTML Form Tag Tutorial (4):

Suppose now you want to add an item like this to ...