Vue3 implements Message component example

Vue3 implements Message component example

In most web products, the global Message component has a large usage scenario. It often appears in scenarios of giving user feedback, information prompts, and dialogues with the system. If you use the traditional component writing method, you need to import the component and register it in components, then call it in the template as a tag, pass in custom props attributes and trigger events through emit. This type of component often has the following disadvantages:

  • Need to be frequently introduced and registered
  • You need to use the component as a tag in the template
  • Additional parameters are required to control the properties and status of components
  • The mounting location of unfriendly custom components will be affected by other components

Therefore, for components such as Message, we hope to be able to call them in JavaScript, pass in custom parameters to control the component state, and do not need to manually mount the component to the end of the body when calling. If you have used mainstream third-party libraries, such as ElementUI plus or Ant Design for Vue, then you must be familiar with their message component API. Next, let’s use Vue3 to implement a global Message component.

The final effect of the component

Component Design

Defining the final component API

Implement a simple Message component, including API types such as text, success, and error. It supports directly passing in a piece of text, and also supports customizing message content, closing delay, and whether to display a close button through component-specific option configuration.

// Message type: text, success, failure ["text", "success", "error"]

// Message options
[String]: message content [Object]: message configuration // option configuration text [String] "" message content duration [Number] 0 The delay in milliseconds for automatic closing, 0 means no automatic closing close [Boolean] false Whether to display the close button // Calling method Message[type](option);

Calling Example

Message.text("This is a message prompt");
Message.error({
    text: "Network error, please try again later",
    duration: 3000,
    close: true
});

Defining component structure

Create a Message folder to store the overall structure of the component, where src contains the component's template, style, and instance files. At the same level, create index.js to expose the entire component so that it can be introduced in projects and business components.

|--- Message
 |--- src
 | |--- Message.vue // component template| |--- Message.less // provide component style support| |--- Message.js // read configuration and render component instance| |--- Instance.js // component instance|---index.js // expose component

Templates and styles

Template

The template is relatively simple. The outer layer is wrapped by animation components, and v-show is used to control the display and closing of messages. The content includes icons, message text, and a configurable manual close button.

<template>
  <!-- Message List-->
  <transition name="slide-fade">
    <div class="message-container" v-show="visibled">
      <!-- Contents -->
      <div class="message-content">

        <!-- Message type icon, determined by the message type, text type does not configure an icon-->
        <div class="message-icon" v-if="config.icon">
          <i :class="config.icon"></i>
        </div>

  <!-- Message text -->
        <span v-text="config.content"></span>

        <!-- Close the message manually -->
        <div class="option" v-if="!config.close">
          <i class="ri-close-fill" @click="onClose"></i>
        </div>

      </div>
    </div>
  </transition>
</template>

Message Icon

It should be noted that the icon is determined by the type in the API call. The icon type is determined when the instance is created. The open source icon library Remix Icon is referenced here. The specific reference method is not described here. The address is: remixicon.cn/

style

Define styles and animations in Message.less.

@radius: 4px;
@normalHeight: 34px;

.message {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  text-align: center;
  box-sizing: border-box;
  z-index: 9999;
  transform: translateZ(9999px);
  padding-top: 28px;
  transition: top .4s ease;

  .message-container {
    margin-bottom: 14px;

    .message-icon {
      display: inline-block;

      i {
        font-size: 18px;
        font-weight: 400;
        margin-top: -3px;
        margin-right: 6px;
        display: inline-block;
        box-sizing: border-box;
        vertical-align: middle;
      }

      .ri-checkbox-circle-fill {
        color: #58c05b;
      }

      .ri-close-circle-fill {
        color: #fd4f4d;
      }

    .message-content {
      display: inline-block;
      padding: 4px 18px;
      height: @normalHeight;
      text-align: left;
      line-height: @normalHeight;
      font-size: 14px;
      font-weight: 400;
      border-radius: @radius;
      color: #595959;
      box-shadow: 0 4px 12px rgba(0, 0, 0, .15);
      background: #ffffff;

      .option {
        display: inline-block;
        pointer-events: all;
        margin-left: 18px;

        i {
          font-size: 18px;
          font-weight: 400;
          margin-top: -3px;
          display: inline-block;
          box-sizing: border-box;
          vertical-align: middle;
          cursor: pointer;
          color: #d9d9d9;
          transition: color 0.2s ease;

          &:hover {
            color: #ff7c75;
            transition: color 0.2s ease;
          }
        }
      }
    }
  }

  .slide-fade-enter-active {
    transition: all .2s ease-out;
  }

  .slide-fade-leave-active {
    transition: all .2s ease;
  }

  .slide-fade-enter-from,
  .slide-fade-leave-to {
    transform: translateY(-20px);
    opacity: 0;
  }
}

Component Scripts

In the component, rendering and unmounting are achieved by obtaining the passed config configuration and removing, and the message opening and manual closing are controlled by onOpen and onClose methods. The specific code is as follows:

<script>
import { reactive, toRefs } from "vue";
export default {
  props: {
    config: { type: Object, default: () => {} }, // message configuration item remove: { type: Function, default: () => {} }, // cancel mount callback },
  setup(props) {
    const state = reactive({
      visibled: false,
    })

    // Open message const onOpen = (config) => {
      setTimeout(() => {
        state.visibled = true;
      }, 10)

      // Remove the message after a specified time if (config.duration !== 0) {
        setTimeout(() => {
          onClose();
        }, config.duration);
      }
    }

    onOpen(props.config)

    //Message close const onClose = () => {
      state.visibled = false;
      setTimeout(() => {
        props.remove()
      }, 200)
    };

    return {
      ...toRefs(state),
      onOpen,
      onClose,
    };
  },
};
</script>

Creating a component instance

Next, we will write the APIs for creating, mounting, and destroying components when calling components in Instance.js. The header introduces Vue's instance creation method and the component template written above:

import { createApp } from 'vue'
import Message from './Message.vue'

Declare an instance operation method, accepting a message configuration parameter cfg

/**
 * Message instance operation * @param {Object} cfg instance configuration */
const createInstance = cfg => {
 const config = cfg || {}
 // 1. Create a package container and set the outer Class attribute and message count // 2. Create an instance and mount it to the body
 
 // 3. Implement the method to cancel the mount and restart the count after canceling the mount}
export default createInstance

1. Create a wrapper container and set the outer Class property

Create a DIV as an outer container to wrap the component and set the corresponding class attribute

let messageNode = document.createElement('div')
let attr = document.createAttribute("class")
attr.value = "message"
messageNode.setAttributeNode(attr)

Message count, we define the height of a message pop-up box as 54 px. When multiple messages are queued and opened, the components are staggered by setting the top value.

const height = 54 // Single message box height const messageList = document.getElementsByClassName('message')
messageNode.style.top = `${messageList.length * height}px`

2. Create an instance and mount it to the body

const app = createApp(Message, {
  config,
  remove() {
    handleRemove()//Remove the element. After the message is closed, unmount and remove it from the Dom.}
})

// Mount the instance and append it to the end of body app.vm = app.mount(messageNode)
document.body.appendChild(messageNode)

app.close = () => {
  handleRemove()
}

return app

3. The method of canceling the mount and resetting the top value is defined

const handleRemove = ()=>{
  app.unmount(messageNode)
  document.body.removeChild(messageNode)
  resetMsgTop()
 }

const resetMsgTop = () => {
  for (let i = 0; i < messageList.length; i++) {
    messageList[i].style.top = `${i * height}px`
  }
}

Implementing the Rendering Instance API

Use Message.js to read the configuration and render.

import createInstance from './Instance.js'

/**
 * Read configuration and render Message
 * @param {Object} typeCfg type configuration * @param {Object/String} cfg custom configuration */
function renderMsg(typeCfg = {}, cfg = '') {
  // Allows direct passing of message content, so the type of the passed-in cfg must be determined const isContent = typeof cfg === 'string'

  // Integrate custom configuration cfg = isContent ? {
    content: cfg
  } : cfg

  const config = Object.assign({}, typeCfg, cfg) // Merge configuration const {
    type = 'text', // message type content = '', // message content duration = 3000, // automatic closing delay time close = false // whether to display the close button } = config

  // Create an instance return createInstance({
    type,
    content,
    duration,
    close
  })
}

Expose text, success, error and other APIs.

export default {
  // Plain text message text(cfg = "") {
    const textCfg = {
      type: "text",
      icon: ''
    }

    return renderMsg(textCfg, cfg);
  },
  // Success prompt success(cfg = "") {
    const successCfg = {
      type: "success",
      icon: 'ri-checkbox-circle-fill'
    }

    return renderMsg(successCfg, cfg);
  },
  // Error message error(cfg = "") {
    const errorCfg = {
      type: "error",
      icon: 'ri-close-circle-fill'
    }

    return renderMsg(errorCfg, cfg);
  },
}

Finally, open this component in the outermost index.js for calling.

import Message from './src/Message.js';

export default Message;

This is the end of this article about Vue3's implementation of the Message component example. For more related Vue3 Message component 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 manual encapsulation pop-up box component message method
  • Detailed explanation of Vue3 encapsulation Message message prompt instance function
  • Write a global Message component based on vue
  • Encapsulation and use of el-message in vue

<<:  Mysql method to copy a column of data in one table to a column in another table

>>:  The easiest way to make a program run automatically at startup in Linux

Recommend

How to convert MySQL horizontally to vertically and vertically to horizontally

Initialize Data DROP TABLE IF EXISTS `test_01`; C...

Detailed explanation of the working principle and solution of Js modularization

Table of contents 1. Modular concept 2. Modulariz...

MySQL 8.0.15 installation tutorial for Windows 64-bit

First go to the official website to download and ...

Reasons and methods for Waiting for table metadata lock in MySQL

When MySQL performs DDL operations such as alter ...

6 Uncommon HTML Tags

First: <abbr> or <acronym> These two s...

The difference between ENTRYPOINT and CMD in Dockerfile

In the Docker system learning tutorial, we learne...

A brief discussion on the role of Vue3 defineComponent

Table of contents defineComponent overload functi...

TypeScript Enumeration Type

Table of contents 1. Overview 2. Digital Enumerat...

ElementUI component el-dropdown (pitfall)

Select and change: click to display the current v...

How to query and update the same table in MySQL database at the same time

In ordinary projects, I often encounter this prob...

In-depth analysis of MySQL lock blocking

In daily maintenance, threads are often blocked, ...

How to get datetime data in mysql, followed by .0

The data type of MySQL is datetime. The data stor...

How to create LVM for XFS file system in Ubuntu

Preface lvm (Logical Volume Manager) logical volu...