vue做移动端经常碰到弹窗的需求, 这里写一个功能简单的vue弹窗

popup.vue


<template>
  <div class=\"popup-wrapper\" v-show=\"visible\" @click=\"hide\">
    <div class=\"popup-text\">{{text}}</div>
  </div>
</template>

组件html结构, 外层divposition:fixed定位, 内层div显示弹窗内容


export default {
  name: \'popup\',
  props: {
    text: { //文字内容
      type: String,
      default: \'\'
    },
    time: { //显示的时长
      type: Number,
      default: 3e3
    },
  },
  data(){
    return {
      visible: false
    }
  },
  methods: {
    open() {
      this.visible = true
      clearTimeout(this.timeout);
      this.$emit(\'show\')
      if(this.time > 0){
        this.timeout = setTimeout(() => {
          this.hide()
        }, this.time)
      }
    },
    hide() {
      this.visible = false
      this.$emit(\'hide\')
      clearTimeout(this.timeout);
    }
  }
}

popup.vue只有2个属性: 文本和显示时间。组件显示隐藏由内部属性visible控制,只暴露给外界open和hide2个方法,2个方法触发对应的事件

测试一下


<template>
  <popup ref=\"popup\" text=\"弹窗内容\" :time=\"1e3\"></popup>
</template>
< >
import Popup from \'@/components/popup\'
  ...
    this.$refs.popup.open()
   ...
</ >

\"在这里插入图片描述\"

插件化

组件功能写好了,但是这种调用方式显得很累赘。举个例子 .js的调用就是 .open(...)没有import,没有ref,当然要先全局引用 。我们写的弹窗能不能这么方便呢,为此需要把popup改写成vue插件。
说是插件,但能配置属性调用方法的还是组件本身,具体是实例化的组件,而且这个实例必须是全局单例,这样不同vue文件唤起popup的时候才不会打架

生成单例


// plugins/popupVm.js
import Popup from \'@/components/popup\'
let $vm
export const factory = (Vue)=> {
  if (!$vm) {
    let Popup = Vue.extend(PopupComponent)
    $vm = new Popup({
      el: document.createElement(\'div\')
    })
    document.body.appendChild($vm.$el)
  }
  return $vm
}

组件实例化后是添加在body上的,props不能写在html里需要js去控制,这里写个方法让属性默认值继续发挥作用


// plugins/util.js
export const setProps = ($vm, options) => {
  const defaults = {}
   .keys($vm.$options.props).forEach(k => {
    defaults[k] = $vm.$options.props[k].default
  })
  const _options = _.assign({}, defaults, options)
  for (let i in _options) {
    $vm.$props[i] = _options[i]
  }
}

// plugins/popupPlugin.js
import { factory } from \'./popupVm\'
import { setProps } from \'./util\'

export default {
  install(Vue) {
     let $vm = factory(Vue);

     const popup = {
      open(options) {
        setProps($vm, options)
        //监听事件
        typeof options.onShow === \'function\' && $vm.$once(\'show\', options.onShow);
        typeof options.onHide === \'function\' && $vm.$once(\'hide\', options.onHide);
        $vm.open();
      },
      hide() {
        $vm.hide()
      },
      //只配置文字
      text(text) {
        this.open({ text })
      }
    }
    
    Vue.prototype.$popup = popup
  }
}

在main.js内注册插件


//main.js
import Vue from \'vue\'
import PopupPlugin from \'@/plugins/popupPlugin\'

Vue.use(PopupPlugin)

在vue框架内调用就非常方便了


< >
  ...
    this.$popup.text(\'弹窗消息\')
  ...
</ >

来源:https://segmentfault.com/a/1190000016313195

收藏 打印