视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
vue弹窗插件实战代码
2020-11-27 22:08:16 责编:小采
文档

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>
<script>
import Popup from '@/components/popup'
 ...
 this.$refs.popup.open()
 ...
</script>

插件化

组件功能写好了,但是这种调用方式显得很累赘。举个例子layer.js的调用就是layer.open(...)没有import,没有ref,当然要先全局引用layer。我们写的弹窗能不能这么方便呢,为此需要把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 = {}
 Object.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框架内调用就非常方便了

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

下载本文
显示全文
专题