vue3弹出层V3Popup实例详解


Posted in Vue.js onJanuary 04, 2021

Vue3-Popup 基于vue3构建的手机端自定义弹层组件。

一款集合了msg、alert、dialog、modal、actionSheet、toast等多种效果的Vue3自定义弹层组件。支持上下左右弹出、圆角、自定义弹层样式、多按钮及长按/右键功能。

vue3弹出层V3Popup实例详解

引入v3popup

// 在main.js中全局引入
import { createApp } from 'vue'
import App from './App.vue'
 
// 引入弹窗组件v3popup
import V3Popup from './components/v3popup'
 
createApp(App).use(V3Popup).mount('#app')

调用方式支持标签式+函数式,根据项目需要选择合适的调用方法。

<!-- 提示框 -->
<v3-popup v-model="showMsg" anim="fadeIn" content="msg提示框测试(3s后窗口关闭)" shadeClose="false" time="3" />
 
<!-- 询问框 -->
<v3-popup v-model="showConfirm" shadeClose="false" title="标题" xclose z-index="2020"
 content="<div style='color:#1be769;padding:20px;'>确认框(这里是确认框提示信息,这里确认框提示信息,这里是确认框提示信息)</div>"
 :btns="[
  {text: '取消', click: () => showConfirm=false},
  {text: '确定', style: 'color:#f90;', click: handleInfo},
 ]"
/>
// 函数式调用
let $el = this.$v3popup({
 title: '标题',
 content: '<div style='color:#f90;padding:10px;'>这里是内容信息!</div>',
 type: 'android',
 shadeClose: false,
 xclose: true,
 btns: [
  {text: '取消', click: () => { $el.close(); }},
  {text: '确认', style: 'color:#f90;', click: () => handleOK},
 ],
 onSuccess: () => {},
 onEnd: () => {}
})

vue3弹出层V3Popup实例详解

vue3中可通过vue3弹出层V3Popup实例详解 和vue3弹出层V3Popup实例详解

 两种方式挂载类似vue2中prototype原型链方法。

通过 vue3弹出层V3Popup实例详解方式挂载。

// vue2中调用
methods: {
 showDialog() {
  this.$v3popup({...})
 }
}
 
// vue3中调用
setup() {
 // 获取上下文
 const { ctx } = getCurrentInstance()
 ctx.$v3popup({...})
}

通过vue3弹出层V3Popup实例详解 方式挂载。

// vue2中调用
methods: {
 showDialog() {
  this.v3popup({...})
 }
}
 
// vue3中调用
setup() {
 const v3popup = inject('v3popup')
 
 const showDialog = () => {
  v3popup({...})
 }
 
 return {
  v3popup,
  showDialog
 }
}

预览效果

vue3弹出层V3Popup实例详解

vue3弹出层V3Popup实例详解

vue3弹出层V3Popup实例详解

vue3弹出层V3Popup实例详解

vue3弹出层V3Popup实例详解

vue3弹出层V3Popup实例详解

vue3弹出层V3Popup实例详解

vue3弹出层V3Popup实例详解

v3popup参数配置

组件支持如下20+种参数灵活配置。

|props参数|
v-model   是否显示弹框
title   标题
content   内容(支持String、带标签内容、自定义插槽内容)***如果content内容比较复杂,推荐使用标签式写法
type   弹窗类型(toast | footer | actionsheet | actionsheetPicker | android | ios)
popupStyle  自定义弹窗样式
icon   toast图标(loading | success | fail)
shade   是否显示遮罩层
shadeClose  是否点击遮罩时关闭弹窗
opacity   遮罩层透明度
round   是否显示圆角
xclose   是否显示关闭图标
xposition  关闭图标位置(left | right | top | bottom)
xcolor   关闭图标颜色
anim   弹窗动画(scaleIn | fadeIn | footer | fadeInUp | fadeInDown)
position  弹出位置(top | right | bottom | left)
follow   长按/右键弹窗(坐标点)
time   弹窗自动关闭秒数(1、2、3)
zIndex   弹窗层叠(默认8080)
teleport  指定挂载节点(默认是挂载组件标签位置,可通过teleport自定义挂载位置) teleport="body | #xxx | .xxx"
btns   弹窗按钮(参数:text|style|disabled|click)
++++++++++++++++++++++++++++++++++++++++++++++
|emit事件触发|
success   层弹出后回调(@success="xxx")
end    层销毁后回调(@end="xxx")
++++++++++++++++++++++++++++++++++++++++++++++
|event事件|
onSuccess  层打开回调事件
onEnd   层关闭回调事件

vpopop.vue模板核心代码

<template>
 <div ref="elRef" v-show="opened" class="vui__popup" :class="{'vui__popup-closed': closeCls}" :id="id">
  <!-- //蒙层 -->
  <div v-if="JSON.parse(shade)" class="vui__overlay" @click="shadeClicked" :style="{opacity}"></div>
  <div class="vui__wrap">
   <div class="vui__wrap-section">
    <div class="vui__wrap-child" :class="['anim-'+anim, type&&'popupui__'+type, round&&'round', position]" :style="[popupStyle]">
     <div v-if="title" class="vui__wrap-tit" v-html="title"></div>
     <div v-if="type=='toast'&&icon" class="vui__toast-icon" :class="['vui__toast-'+icon]" v-html="toastIcon[icon]"></div>
     <!-- 判断插槽是否存在 -->
     <template v-if="$slots.content">
      <div class="vui__wrap-cnt"><slot name="content" /></div>
     </template>
     <template v-else>
      <div v-if="content" class="vui__wrap-cnt" v-html="content"></div>
     </template>
     <slot />
     <div v-if="btns" class="vui__wrap-btns">
      <span v-for="(btn, index) in btns" :key="index" class="btn" :style="btn.style" @click="btnClicked($event, index)" v-html="btn.text"></span>
     </div>
     <span v-if="xclose" class="vui__xclose" :class="xposition" :style="{'color': xcolor}" @click="close"></span>
    </div>
   </div>
  </div>
 </div>
</template>
 
/**
 * @Desc  Vue3自定义弹出层组件V3Popup
 * @Time  andy by 2020-12
 * @About Q:282310962 wx:xy190310
 */
<script>
 import { onMounted, ref, reactive, watch, toRefs, nextTick } from 'vue'
 let $index = 0, $locknum = 0, $timer = {}
 export default {
  props: {
   // 接收父组件v-model值,如果v-model:open,则这里需写open: {...}
   modelValue: { type: Boolean, default: false },
   // 标识符,相同ID共享一个实例
   id: {
    type: String, default: ''
   },
   title: String,
   content: String,
   type: String,
   popupStyle: String,
   icon: String,
   shade: { type: [Boolean, String], default: true },
   shadeClose: { type: [Boolean, String], default: true },
   opacity: { type: [Number, String], default: '' },
   round: Boolean,
   xclose: Boolean,
   xposition: { type: String, default: 'right' },
   xcolor: { type: String, default: '#333' },
   anim: { type: String, default: 'scaleIn' },
   position: String,
   follow: { type: Array, default: null },
   time: { type: [Number, String], default: 0 },
   zIndex: { type: [Number, String], default: '8080' },
   teleport: [String, Object],
   btns: {
    type: Array, default: null
   },
   onSuccess: { type: Function, default: null },
   onEnd: { type: Function, default: null },
  },
  emits: [
   'update:modelValue'
  ],
  setup(props, context) {
   const elRef = ref(null)
 
   const data = reactive({
    opened: false,
    closeCls: '',
    toastIcon: {
     ...
    }
   })
 
   onMounted(() => {
    ...
   })
 
   // 监听弹层v-model
   watch(() => props.modelValue, (val) => {
    if(val) {
     open()
    }else {
     close()
    }
   })
 
   // 打开弹层
   const open = () => {
    if(data.opened) return
    data.opened = true
    typeof props.onSuccess === 'function' && props.onSuccess()
 
    const dom = elRef.value
    dom.style.zIndex = getZIndex() + 1
 
    ...
 
    // 倒计时
    if(props.time) {
     $index++
     // 避免重复操作
     if($timer[$index] !== null) clearTimeout($timer[$index])
     $timer[$index] = setTimeout(() => {
      close()
     }, parseInt(props.time) * 1000)
    }
 
    // 长按|右键菜单
    if(props.follow) {
     ...
    }
   }
 
   // 关闭弹层
   const close = () => {
    if(!data.opened) return
 
    data.closeCls = true
    setTimeout(() => {
     ...
 
     context.emit('update:modelValue', false)
     typeof props.onEnd === 'function' && props.onEnd()
    }, 200)
   }
 
   // 点击遮罩层
   const shadeClicked = () => {
    if(JSON.parse(props.shadeClose)) {
     close()
    }
   }
   // 按钮事件
   const btnClicked = (e, index) => {
    let btn = props.btns[index];
    if(!btn.disabled) {
     typeof btn.click === 'function' && btn.click(e)
    }
   }
   
   ...
 
   return {
    ...toRefs(data),
    elRef,
    close,
    shadeClicked,
    btnClicked,
   }
  }
 }
</script>

vue2.x中通过Vue.extends扩展函数实例来实现挂载弹窗到body上。

vue3.x中则可以通过 vue3弹出层V3Popup实例详解 和 vue3弹出层V3Popup实例详解  vue3弹出层V3Popup实例详解 来实现挂载到body上。

import { createApp } from 'vue'
import PopupConstructor from './popup.vue'
 
let $inst
// 创建挂载实例
let createMount = (opts) => {
 const mountNode = document.createElement('div')
 document.body.appendChild(mountNode)
 
 const app = createApp(PopupConstructor, {
  ...opts, modelValue: true,
  remove() {
   app.unmount(mountNode)
   document.body.removeChild(mountNode)
  }
 })
 return app.mount(mountNode)
}
 
function V3Popup(options = {}) {
 options.id = options.id || 'v3popup_' + generateId()
 $inst = createMount(options)
 
 return $inst
}
 
V3Popup.install = app => {
 app.component('v3-popup', PopupConstructor)
 // app.config.globalProperties.$v3popup = V3Popup
 app.provide('v3popup', V3Popup)
}

这样就可以实现函数式来调用组件了。

另外vue2.x中给v-model传值 this.$emit('input', false)

vue3中modelValue是默认的。 则是 context.emit('update:modelValue', false)

如果定义的是v-model:visible,则需要先在props: { visible: Boolean }中声明,然后context.emit('update:visible': false)

Ok,基于vue3.0开发自定义弹框组件就介绍到这里。感兴趣的可以动手去试试哈。??

到此这篇关于vue3弹出层V3Popup实例详解的文章就介绍到这了,更多相关vue3弹出层内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
Vue 的 v-model用法实例
Nov 23 Vue.js
VUE中鼠标滚轮使div左右滚动的方法详解
Dec 14 Vue.js
Vue 组件注册全解析
Dec 17 Vue.js
Vue+scss白天和夜间模式切换功能的实现方法
Jan 05 Vue.js
详解Vue2的diff算法
Jan 06 Vue.js
基于vuex实现购物车功能
Jan 10 Vue.js
如何在vue 中使用柱状图 并自修改配置
Jan 21 Vue.js
vue登录页实现使用cookie记住7天密码功能的方法
Feb 18 Vue.js
vue实现无缝轮播效果(跑马灯)
May 14 Vue.js
vue中的可拖拽宽度div的实现示例
Apr 08 Vue.js
vue+elementUI实现表格列的显示与隐藏
Apr 13 Vue.js
vue 把二维或多维数组转一维数组
Apr 24 Vue.js
vue3自定义dialog、modal组件的方法
Jan 04 #Vue.js
vue中父子组件的参数传递和应用示例
Jan 04 #Vue.js
如何在VUE中使用vue-awesome-swiper
Jan 04 #Vue.js
vue项目如何监听localStorage或sessionStorage的变化
Jan 04 #Vue.js
手写Vue源码之数据劫持示例详解
Jan 04 #Vue.js
vue+vant 上传图片需要注意的地方
Jan 03 #Vue.js
vue调用微信JSDK 扫一扫,相册等需要注意的事项
Jan 03 #Vue.js
You might like
PHP常用特殊运算符号和函数总结(php新手入门必看)
2013/02/02 PHP
php生成动态验证码gif图片
2015/10/19 PHP
php实现异步将远程链接上内容(图片或内容)写到本地的方法
2016/11/30 PHP
PHP反射基础知识回顾
2020/09/10 PHP
获取JavaScript用户自定义类的类名称的代码
2007/03/08 Javascript
Jquery 最近浏览过的商品的功能实现代码
2010/05/14 Javascript
jquery ajax的success回调函数中实现按钮置灰倒计时
2013/11/19 Javascript
Angularjs实现带查找筛选功能的select下拉框示例代码
2016/10/04 Javascript
基于JavaScript实现全选、不选和反选效果
2017/02/15 Javascript
详解nodeJS之二进制buffer对象
2017/06/03 NodeJs
客户端(vue框架)与服务器(koa框架)通信及服务器跨域配置详解
2017/08/26 Javascript
Web开发使用Angular实现用户密码强度判别的方法
2017/09/27 Javascript
基于JSONP原理解析(推荐)
2017/12/04 Javascript
Angularjs实现数组随机排序的方法
2018/10/02 Javascript
Python 冒泡,选择,插入排序使用实例
2015/02/05 Python
Python中使用hashlib模块处理算法的教程
2015/04/28 Python
python通过定义一个类实例作为ftp回调方法
2015/05/04 Python
Python使用bs4获取58同城城市分类的方法
2015/07/08 Python
tensorflow 恢复指定层与不同层指定不同学习率的方法
2018/07/26 Python
Pytorch中accuracy和loss的计算知识点总结
2019/09/10 Python
用CSS3将你的设计带入下个高度
2009/08/08 HTML / CSS
利用CSS3的checked伪类实现OL的隐藏显示的方法
2010/12/18 HTML / CSS
html5 css3网站菜单实现代码
2013/12/23 HTML / CSS
全球最大的中文旅行网站:去哪儿网
2017/11/16 全球购物
Pam & Gela官网:美国性感前卫女装品牌
2018/07/19 全球购物
服务员岗位职责
2014/01/29 职场文书
安全生产承诺书
2014/03/26 职场文书
股东合作协议书
2014/04/14 职场文书
2014教师研修学习体会
2014/07/08 职场文书
群众路线教育实践活动思想汇报(2014特荐篇)
2014/09/16 职场文书
2014副镇长民主生活会个人对照检查材料思想汇报
2014/09/30 职场文书
篮球友谊赛通讯稿
2014/10/10 职场文书
离职感谢信
2015/01/21 职场文书
2015年“七七卢沟桥事变”纪念活动总结
2015/03/24 职场文书
读《工匠精神》有感:热爱工作,精益求精
2019/12/28 职场文书
「海贼王」112.9万粉丝纪念图标公布
2022/03/21 日漫