vue3 自定义插件[plugins]

2,958 阅读1分钟

vue3 自定义插件[plugins]

插件基本语法

createApp(component, props)

  • createApp功能是创建一个实例
  • createApp有两个参数,第一个参数是根组件,第二个参数是要传递给根组件的props

plugin

  • 插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。
  • 一个插件可以是一个拥有 install() 方法的对象,也可以直接是一个安装函数本身。

简单事例

// install
const myPlugin = {
  install(app, options) {
    // 配置此应用
  }
}
// 无install
const myPlugin = (app, options) => {

}
// 使用
import { createApp } from 'vue'
const app = createApp({})
app.use(myPlugin, {
  /* 可选的选项 */
})

指令可以做哪些事情

  • 自定义MessageBox(alert)模态框
  • 自定义Toast
  • 图片点击放大
  • 优惠券选择弹层
  • 商品sku选择弹层
  • ......

plugin实战

自定义messageBox

// messageBox/index.vue
<template>
  <div class="confirm-box" v-if="showMessage">
    <div class="confirm">
      <div class="content">
        {{ confirmObj.content }}
      </div>
      <!-- 弹框描述 -->
      <div v-if="confirmObj.description" class="description">
        {{ confirmObj.description }}
      </div>
      <div class="confirm-btn">
        <div class="btn border" @click="cancel" v-if="confirmObj.cancelText">{{ confirmObj.cancelText }}</div>
        <div
          class="btn primary"
          :class="{ 'border-l': confirmObj.cancelText, 'block-btn': !confirmObj.cancelText }"
          @click="sure"
        >
          {{ confirmObj.confirmText || '确定' }}
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

// 接收props
const props = defineProps({
  myProvide: {
    type: Function,
    required: true
  },
})
const showMessage = ref(false)  // 控制弹窗显示/隐藏
const confirmObj = ref({})  // 弹窗内容接收对象
let callback = () => {} // 存储resolve

const showConfirm = (obj) => {
  confirmObj.value = obj
  showMessage.value = true
  return new Promise((resolve) => {
    callback = resolve
  })
}
const cancel = () => {
  callback('cancel')
  showMessage.value = false
}
const sure = () => {
  callback('confirm')
  showMessage.value = false
}

onMounted(() => {
  props.myProvide('$confirm', showConfirm)  // confirm前加$标记全局变量
})

</script>

<style lang="less">
.pop-mask-overflow {
  overflow: hidden;
}
.confirm-box {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 10000000;
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.5);
  .confirm {
    width: 600px;
    padding: 80px 60px 72px;
    background: #fff;
    border-radius: 2px;
  }
  .content {
    font-size: 40px;
    line-height: 56px;
    color: #000;
  }
  .description {
    margin-top: 32px;
    font-size: 28px;
    font-weight: 300;
    color: #555555;
    font-family: PingFangSC-Light, PingFang SC;
  }
  .confirm-btn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 50px;
    margin-top: 80px;
    .btn {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 80px;
      width: 224px;
      font-size: 28px;
      line-height: 40px;
      color: #000;
      &.border {
        border: 1px solid #333;
      }
      &.primary {
        background: #000000;
        color: #fff;
      }

      &.block-btn {
        width: 100%;
      }
    }
  }
}
</style>
// messageBox/index.vue
import {createApp} from 'vue'
import Confirm from './index.vue'

export default {
  install: (app) => {
    const myProvide = app.provide
    // 需要使用应用根组建提供的provide,确保子节点都可以通过inject使用
    createApp(Confirm, {
      myProvide
    }).mount('#messageBox') // 挂载到独立的dom上,需要在html中添加dom节点
  }
}
// 使用
// 全局注册
app.use(MessageBox)

// 组件内
const $confirm = inject('$confirm')
const click = () => {
  $confirm({
    content: '测试title',
    desc: '测试content',
    confirmText: '确定',
    cancelText: '取消'
  }).then(r => console.log(r))
}

玫瑰花宝典