Vue3新特性的学习(十一)—— 如何开发插件

1,635 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

今天主要学的是Vue3中如何开发插件。

插件开发

第一步:新建插件文件

新建一个plugins文件夹,以toast插件为例,toast文件夹包含两个文件,toast.vueindex.ts

image.png

第二步,写入插件所需内容(以toast插件为例)

toast中,这里简单做个示范,具体写的时候根据具体需求去写:

// toast.vue
<template>
  <div class="toast-wrap">
    {{ message }}
  </div>
</template>

<script>
export default {
  name: 'my-toast',
  props: {
    message: {
      type: String,
      default: '',
    },
  },
};
</script>

<style scoped>
.toast-wrap {
  background-color: rgba(0, 0, 0, 0.8);
  padding: 8px 15px;
  font-size: 14px;
  color: #ffffff;
  text-align: center;
  position: fixed;
  z-index: 99;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 5px;
}
</style>

// index.ts
import MyToast from './toast.vue';
import { createVNode, render } from 'vue';
interface IOptions {
  message: string;
  duration?: number;
  onClose?: Function;
}

export default {
  install: (app: any) => {
    //是否存在toast,防止toast在未销毁前,连续点击按钮生成多个toast
    let isToast = false;
    // app.config.globalProperties注册全局方法,相当于vue2的Vue.prototype
    app.config.globalProperties.$myToast = function (opts: IOptions) {
      //如果toast不存在,开始创建toast
      if (!isToast) {
        isToast = true; //在toast未销毁前,不执行以下程序
        //创建虚拟节点
        let vm: any = createVNode(MyToast);
        //创建div容器
        let container = document.createElement('div');
        //渲染虚拟节点
        render(vm, container);
        //将创建好的div元素添加到body元素内
        document.body.appendChild(container);
        //设置toast.vue文件中的props选项内部的message的值
        vm.component.props.message = opts.message || '';
        let duration = opts.duration || 2000;
        setTimeout(() => {
          //销毁toast
          document.body.removeChild(container);
          //toast销毁后将isToast设置为false,可以再次创建toast
          isToast = false;
          //如果存在onClose方法
          if (opts.onClose) {
            //调用onClose方法
            opts.onClose();
          }
        }, duration);
      }
    };
  },
};

第三步:全局导入

main.ts中导入使用:

import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import MyToast from './plugins/my-toast';

let app = createApp(App).use(store).use(router);
app.use(MyToast);
app.mount('#app');

第四步,导入页面中使用

<template>
  <div>
    <button @click="showToast()">显示toast</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, getCurrentInstance } from 'vue';
export default defineComponent({
  name: 'show-toast',
  setup() {
    //getCurrentInstance:可以获取到组件的实例
    let { proxy }: any = getCurrentInstance(); // 代替this
    let showToast = () => {
      proxy.$myToast({
        message: '我是toast插件',
        duration: 3000,
        onClose: () => {
          console.log('已关闭');
        },
      });
    };
    return {
      showToast,
    };
  },
});
</script>