preface

Recently, I was reconstructing an old project with VUe3. I came across toast component rewrite and explored it, mainly learning UI encapsulation methods of Vant and Element-UI

Ready to demand

  1. If you want to build an API that can be called and mounted toa Vue instance, you can call it in the SFC using this.$toast
  2. Write a toast.vue template for rendering
  3. Write a toast.ts export toast method and provide it to Vue for mounting
  4. Referenced in main.ts for global mount

Further refinement

1. The template
  • Provide a message argument for popover content
  • You need a fade-in effect, so you need transition and a showToast state
2. Export method
  • Generate instances from templates
  • Mount the instance to the DOM
  • Provide a duration and set a duration timer
  • Delete the DOM instance after the timer is executed
  • Finally, export a mountable object
3. Create an instance
  • Write a generic Composition API
  • Export the mounted instance
  • Export the uninstallation method of the corresponding instance

code

1. Template Toast. Vue
<style lang="less">
.toast {
  position: fixed;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  margin: auto;
  padding: 0.1rem;
  max-width: 80%;
  border-radius: 0.05rem;
  color: #fff;
  background: rgba(0.0.0.0.7);
  font-size: 0.28rem;
  z-index: 99999;
  transition: opacity 0.3s linear;
}

.toast-wrapper-enter-from,
.toast-wrapper-leave-to {
  opacity0;
}
</style>
<template>
  <transition name="toast-wrapper">
    <div class="toast" v-show="showToast">{{ message }}</div>
  </transition>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  // Message content
  props: ['message'].data() {
    return {
      // state
      showToastfalse}}})</script>
Copy the code
2. Generate instance usemountComponent.ts

import { Component, createApp } from 'vue'
export function useMountComponent(rootComponent: Component{
  const app = createApp(rootComponent);
  const root = document.createElement('div');
  document.body.appendChild(root);
  return {
    instance: app.mount(root),
    unmount() {
      app.unmount();
      document.body.removeChild(root); }}; }Copy the code
3. Export method index.ts
import ToastConstructor from './Toast.vue'
import { nextTick, createVNode, App } from 'vue';
import { useMountComponent } from '.. /.. /lib/utils/useMountComponent'
interface ToastOption {
  message: string,
  duration: number
}

const toast = (options: ToastOption | string) = > {
  const duration = typeofoptions ! = ='string' ? options.duration : 3000
  const { instance, unmount } = useMountComponent(createVNode(
    ToastConstructor,
    {
      messagetypeof options === 'string' ? options : options.message
    }
  ));
  
  // The agent that gets the instance and the data agent can get the DOM object data and set the state
  const { proxy, data } = instance.$
  const RemoveSelf = function (event: TransitionEvent{
    unmount()
  }
  
  // Perform show and disappear after the TOAST instance is mounted to the DOM
  nextTick(() = > {
    data.showToast = trueproxy? .$el.removeEventListener('transitionend', RemoveSelf)
    ~duration && (setTimeout(function ({
      data.showToast = falseproxy? .$el.addEventListener('transitionend', RemoveSelf)
    }, duration));
  });
  return instance;
}


export default {
  // The install method is required to mount objects
  install(app: App) = > {
    app.config.globalProperties.$toast = toast
  }
}
Copy the code
4. Mount main.ts globally

import { createApp } from 'vue'
import Toast from './components/toast/index'

const app = createApp(App)
app.use(Toast)
Copy the code
5. Call

export default defineComponent({
  name"TestToast".setup() { 
     const { proxy } = getCurrentInstance() asComponentInternalInstance proxy? .$toast('test in setup'); 
   },
   methods: {TestToast() {
       this.$toast('test in method')}}});Copy the code

conclusion

Getting an instance and modifying its properties in Vue3 feels a little strange and is not as convenient as in VUe2. This may be a minor side effect of proxy