vue 全局插件制作

651 阅读1分钟

因为业务需求,制作了一个全局的活动弹窗,归纳一下主要用到的知识点。

制作一个组件

由于ui组件库使用的是vant,制作起来比较简单

/src/plugins/activityPopup/index.vue

<template>
  <van-popup class="activity-popup" @close="onClose" v-model="show" closeable>
    <div class="wrapper" @click.stop="onClick">
      <van-image
        width="324"
        height="400"
        :src="img"
      />
    </div>
  </van-popup>
</template>

<script>
export default {
  name: 'ActivityPopup',
  data () {
    return {
      show: true,
      img: require('./images/user.png')
    }
  }
}
</script>

<style lang="scss" scoped>
.activity-popup {
  background: none;
  ::v-deep .van-popup__close-icon--top-right {
    top: 0;
    right: 25px;
    color: white;
  }
}
</style>

构造组件

/src/plugins/activityPopup/index.js

import vue from 'vue'
import ActivityPopup from './index.vue'

// 组件构造器,构造出一个 vue组件实例
const ActivityPopupConstructor = vue.extend(ActivityPopup)

function showActivityPopup ({show = true, img, callBack, click, close}) {
  const activityPopupDom = new ActivityPopupConstructor({
    el: document.createElement('div'),
    data () {
      return {
        show,
        img
      }
    },
    methods: {
      onClick () {
        click && (typeof click === 'function') && click()
        this.show = false
      },
      onClose () {
        document.body.removeChild(activityPopupDom.$el)
        close && (typeof close === 'function') && close()
      }
    }
  })
  document.body.appendChild(activityPopupDom.$el)
  callBack && (typeof callBack === 'function') && callBack()
}

function registryActivityPopup (Vue) { 
  Vue.prototype.$activitpopup = showActivityPopup
}

vue.use(registryActivityPopup)

其中核心是 vue.extend,以下是官方解释:

使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

我理解为不包含components的一个vue实例,其余的option都可以在构造函数中混入且覆盖原有option

使用

/src/main.js

// 全局活动弹窗
import './plugins/activityPopup/index.js'

在需要使用的地方

this.$activitpopup({
    show: true,
    img: require('./plugins/activityPopup/images/user.png'),
    callBack: () => {
        console.log('rendered')
    },
    click: () => {
        console.log('click')
        this.$router.push({name: 'newYear2021'})
    },
    close: () => {
        console.log('close')
    }
})

值得注意的是,目前这个插件多次调用会多次产生dom,考虑到可能需要弹出不一样的东西,暂时没有处理。