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实现坐标拾取器功能示例
Nov 18 Vue.js
vue 使用 sortable 实现 el-table 拖拽排序功能
Dec 26 Vue.js
vue3+typeScript穿梭框的实现示例
Dec 29 Vue.js
vue中父子组件的参数传递和应用示例
Jan 04 Vue.js
如何在vue中使用HTML 5 拖放API
Jan 14 Vue.js
聊聊vue 中的v-on参数问题
Jan 29 Vue.js
vue中axios封装使用的完整教程
Mar 03 Vue.js
vue中利用mqtt服务端实现即时通讯的步骤记录
Jul 01 Vue.js
Vue图片裁剪组件实例代码
Jul 02 Vue.js
详细聊聊vue中组件的props属性
Nov 02 Vue.js
vue实现登陆页面开发实践
May 30 Vue.js
vue css 相对路径导入问题级踩坑记录
Jun 05 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时间戳 strtotime()使用方法和技巧
2013/10/29 PHP
Laravel框架实现调用百度翻译API功能示例
2019/05/30 PHP
Yii框架中使用PHPExcel的方法分析
2019/07/25 PHP
PHP getID3类的使用方法学习笔记【附getID3源码下载】
2019/10/18 PHP
JSON无限折叠菜单编写实例
2013/12/16 Javascript
用js模拟struts2的多action调用示例
2014/05/19 Javascript
javascript实现点击提交按钮后显示loading的方法
2015/07/03 Javascript
jQuery实现淡入淡出二级下拉导航菜单的方法
2015/08/28 Javascript
学习使用jquery iScroll.js移动端滚动条插件
2020/03/24 Javascript
jQuery插件学习教程之SlidesJs轮播+Validation验证
2016/07/12 Javascript
Bootstrap免费字体和图标网站(值得收藏)
2017/03/16 Javascript
iOS + node.js使用Socket.IO框架进行实时通信示例
2017/04/14 Javascript
NodeJS实现微信公众号关注后自动回复功能
2017/05/31 NodeJs
vue中v-for循环给标签属性赋值的方法
2018/10/18 Javascript
vue动态添加路由addRoutes之不能将动态路由存入缓存的解决
2019/02/19 Javascript
vue App.vue中的公共组件改变值触发其他组件或.vue页面监听
2019/05/31 Javascript
JavaScript变量作用域及内存问题实例分析
2019/06/10 Javascript
js实现简单的点名器随机色实例代码
2020/09/20 Javascript
Python实现的选择排序算法示例
2017/11/29 Python
同时安装Python2 &amp; Python3 cmd下版本自由选择的方法
2017/12/09 Python
python pandas库的安装和创建
2019/01/10 Python
Python如何对XML 解析
2020/06/28 Python
使用sublime text3搭建Python编辑环境的实现
2021/01/12 Python
澳洲在线厨具商店:Kitchen Style
2018/05/05 全球购物
国际象棋商店:The Chess Store
2018/07/09 全球购物
几个Linux面试题笔试题
2016/08/01 面试题
英语翻译系毕业生求职信
2013/09/29 职场文书
建材业务员岗位职责
2013/12/08 职场文书
2014元旦晚会策划方案
2014/02/19 职场文书
小学班主任寄语大全
2014/04/04 职场文书
我的中国梦演讲稿1000字
2014/08/19 职场文书
2014个人年度工作总结
2014/12/15 职场文书
邀请书模板
2015/02/02 职场文书
钓鱼岛事件感想
2015/08/11 职场文书
python开发实时可视化仪表盘的示例
2021/05/07 Python
python常见的占位符总结及用法
2021/07/02 Python