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 $router和$route的区别详解
Dec 02 Vue.js
vue使用echarts图表自适应的几种解决方案
Dec 04 Vue.js
vue调用微信JSDK 扫一扫,相册等需要注意的事项
Jan 03 Vue.js
vue如何使用rem适配
Feb 06 Vue.js
vue项目配置 webpack-obfuscator 进行代码加密混淆的实现
Feb 26 Vue.js
Vue2.x-使用防抖以及节流的示例
Mar 02 Vue.js
vue.js Router中嵌套路由的实用示例
Jun 27 Vue.js
详解Vue项目的打包方式(生成dist文件)
Jan 18 Vue.js
vue中的可拖拽宽度div的实现示例
Apr 08 Vue.js
vue实力踩坑之push当前页无效
Apr 10 Vue.js
vue报错function () { [native code] },无法出现我们想要的内容 Unknown custom element
Apr 11 Vue.js
vue项目打包后路由错误的解决方法
Apr 13 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.ini中添加extension=php_mysqli.dll指令的说明
2007/06/14 PHP
PHP 删除文件与文件夹操作 unlink()与rmdir()这两个函数的使用
2011/07/17 PHP
开源php中文分词系统SCWS安装和使用实例
2014/04/11 PHP
PHP批量删除、清除UTF-8文件BOM头的代码实例
2014/04/14 PHP
Symfony2学习笔记之控制器用法详解
2016/03/17 PHP
PHP中如何防止外部恶意提交调用ajax接口
2016/04/11 PHP
php将一维数组转换为每3个连续值组成的二维数组
2016/05/06 PHP
window.onload 加载完毕的问题及解决方案(下)
2009/07/09 Javascript
使用JavaScript 实现各种跨域的方法
2013/05/08 Javascript
javascript中的altKey 和 Event属性大全
2015/11/06 Javascript
Bootstrap基本插件学习笔记之Alert警告框(20)
2016/12/08 Javascript
angularjs路由传值$routeParams详解
2020/09/05 Javascript
使用Bootstrap4 + Vue2实现分页查询的示例代码
2017/12/21 Javascript
vue项目引入字体.ttf的方法
2018/09/28 Javascript
小程序云开发获取不到数据库记录的解决方法
2019/05/18 Javascript
JavaScript之数组扁平化详解
2019/06/03 Javascript
layui 解决form表单点击无反应的问题
2019/10/25 Javascript
深入浅析golang zap 日志库使用(含文件切割、分级别存储和全局使用等)
2020/02/19 Javascript
JavaScript 装逼指南(js另类写法)
2020/05/10 Javascript
[01:30:15]DOTA2-DPC中国联赛 正赛 Ehome vs Aster BO3 第二场 2月2日
2021/03/11 DOTA
python正则表达式的使用
2017/06/12 Python
python爬虫系列Selenium定向爬取虎扑篮球图片详解
2017/11/15 Python
python3 发送任意文件邮件的实例
2018/01/23 Python
Pycharm无法使用已经安装Selenium的解决方法
2018/10/13 Python
Python Switch Case三种实现方法代码实例
2020/06/18 Python
python 牛顿法实现逻辑回归(Logistic Regression)
2020/10/15 Python
使用python将微信image下.dat文件解密为.png的方法
2020/11/30 Python
保安自我鉴定范文
2013/12/08 职场文书
C++程序员求职信范文
2014/04/14 职场文书
运动会广播稿50字-100字
2014/10/11 职场文书
旷课检讨书500字
2014/10/14 职场文书
2015年上半年物业工作总结
2015/03/30 职场文书
旅行社计调工作总结
2015/08/12 职场文书
pytorch fine-tune 预训练的模型操作
2021/06/03 Python
Python3 多线程(连接池)操作MySQL插入数据
2021/06/09 Python
Windows7下FTP搭建图文教程
2022/08/05 Servers