基于Vue.js+Nuxt开发自定义弹出层组件


Posted in Javascript onOctober 09, 2020

今天给大家分享VPopup 基于Vue.js构建的轻量级移动端弹出框组件,详情如下所示:

一款融合了Vant、NutUI等热门Vue组件库中的Popup弹层、Dialog对话框、Toast提示框、ActionSheet动作面板框、Notify通知框等功能。

基于Vue.js+Nuxt开发自定义弹出层组件

快速使用

在main.js中引入组件

// 引入弹窗Popup
import Popup from './components/popup'
Vue.use(Popup)

支持如下两种 组件式 及 函数式 调用插件。

组件式

<template>
 <view id="root">
 ...
 
 <!-- 弹窗模板 -->
 <v-popup 
  v-model="showDialog" 
  anim="scaleIn" 
  title="标题"
  content="这里显示弹出框内容!" 
  shadeClose="false" 
  xclose
  :btns="[
  {...},
  {...},
  ]"
 />
 </view>
</template>

函数式

<script>
 export default {
 ...
 methods: {
  handleShowDialog() {
  let $el = this.$vpopup({
   title: '标题',
   content: '这里显示弹出框内容!',
   anim: 'scaleIn',
   shadeClose: false,
   xclose: true,
   onClose: () => {
   console.log('vpopup is closed!')
   },
   btns: [
   {text: '关闭'},
   {
    text: '确定',
    style: 'color:#00e0a1',
    click: () => {
    $el.close()
    }
   }
   ]
  });
  }
 }
 }
</script>

在实际项目开发中,大家可根据需要自行选择调用。

基于Vue.js+Nuxt开发自定义弹出层组件

msg信息提示

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

<script>
 export default {
 ...
 methods: {
  handleShowDialog() {
  let $el = this.$vpopup({
   title: '标题',
   content: '这里显示弹出框内容!',
   anim: 'scaleIn',
   shadeClose: false,
   xclose: true,
   onClose: () => {
   console.log('vpopup is closed!')
   },
   btns: [
   {text: '关闭'},
   {
    text: '确定',
    style: 'color:#00e0a1',
    click: () => {
    $el.close()
    }
   }
   ]
  });
  }
 }
 }
</script>

ActionSheet动作面板框

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

<!-- ActionSheet底部弹出式菜单 -->
<v-popup v-model="showActionSheet" anim="footer" type="actionsheet" :z-index="1011"
 content="弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内"
 :btns="[
 {text: '拍照', style: 'color:#09f;', disabled: true, click: handleInfo},
 {text: '从手机相册选择', style: 'color:#00e0a1;', click: handleInfo},
 {text: '保存图片', style: 'color:#e63d23;', click: () => null},
 {text: '取消', click: () => showActionSheet=false},
 ]"
/>

IOS风格弹窗

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

<!-- Ios风格样式 -->
<v-popup v-model="showIos1" type="ios" shadeClose="false" title="标题内容" z-index="1990"
	content="弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内"
	:btns="[
		{text: '知道了', click: () => showIos1=false},
		{text: '确定', style: 'color:#00e0a1;', click: handleInfo},
	]"
>
</v-popup>

Toast加载提示框

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

<!-- Toast弹窗 -->
<v-popup v-model="showToast" type="toast" icon="loading" time="5" content="加载中..." />
<v-popup v-model="showToast" type="toast" icon="success" shade="false" time="3" content="成功提示" />
<v-popup v-model="showToast" type="toast" icon="fail" shade="false" time="3" content="失败提示" />

emmm~~ 看了如上效果,是不是觉得还不错哟!那就继续往下看实现过程吧?

弹窗参数配置

弹窗支持如下参数配置,大家根据需要自行组合搭配使用。

@@Props
------------------------------------------
v-model 当前组件是否显示
title 标题
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)
btns 弹窗按钮(参数:text|style|disabled|click)
 
@@$emit
------------------------------------------
open 打开弹出层时触发(@open="xxx")
close 关闭弹出层时触发(@close="xxx")
 
@@Event
------------------------------------------
onOpen 打开弹窗回调
onClose 关闭弹窗回调

弹窗template模板

<template>
 <div v-show="opened" class="nuxt__popup" :class="{'nuxt__popup-closed': closeCls}" :id="id">
 <div v-if="JSON.parse(shade)" class="nuxt__overlay" @click="shadeClicked" :style="{opacity}"></div>
 <div class="nuxt__wrap">
 <div class="nuxt__wrap-section">
 <div class="nuxt__wrap-child" :class="['anim-'+anim, type&&'popui__'+type, round&&'round', position]" :style="popupStyle">
  <div v-if="title" class="nuxt__wrap-tit" v-html="title"></div>
  <div v-if="type=='toast'&&icon" class="nuxt__toast-icon" :class="['nuxt__toast-'+icon]" v-html="toastIcon[icon]"></div>
  <template v-if="$slots.content"><div class="nuxt__wrap-cnt"><slot name="content" /></div></template>
  <template v-else><div v-if="content" class="nuxt__wrap-cnt" v-html="content"></div></template>
  <slot />
  <div v-if="btns" class="nuxt__wrap-btns">
  <span v-for="(btn,index) in btns" :key="index" class="btn" :style="btn.style" v-html="btn.text"></span>
  </div>
  <span v-if="xclose" class="nuxt__xclose" :class="xposition" :style="{'color': xcolor}" @click="close"></span>
 </div>
 </div>
 </div>
 </div>
</template>
/**
 * @Desc VueJs自定义弹窗组件VPopup
 * @Time andy by 2020-10-06
 * @About Q:282310962 wx:xy190310
 */
<script>
 let $index = 0, $lockCount = 0, $timer = {};
 export default {
 props: {
 ...
 },
 data() {
 return {
 opened: false,
 closeCls: '',
 toastIcon: {
  ...
 }
 }
 },
 watch: {
 value(val) {
 const type = val ? 'open' : 'close';
 this[type]();
 },
 },
 methods: {
 // 打开弹窗
 open() {
 if(this.opened) return;
 this.opened = true;
 this.$emit('open');
 typeof this.onOpen === 'function' && this.onOpen();
 
 if(JSON.parse(this.shade)) {
  if(!$lockCount) {
  document.body.classList.add('nt-overflow-hidden');
  }
  $lockCount++;
 }
 
 // 倒计时关闭
 if(this.time) {
  $index++;
  if($timer[$index] !== null) clearTimeout($timer[$index])
  $timer[$index] = setTimeout(() => {
  this.close();
  }, parseInt(this.time) * 1000);
 }
 
 if(this.follow) {
  this.$nextTick(() => {
  let obj = this.$el.querySelector('.nuxt__wrap-child');
  let oW, oH, winW, winH, pos;
 
  oW = obj.clientWidth;
  oH = obj.clientHeight;
  winW = window.innerWidth;
  winH = window.innerHeight;
  pos = this.getPos(this.follow[0], this.follow[1], oW, oH, winW, winH);
 
  obj.style.left = pos[0] + 'px';
  obj.style.top = pos[1] + 'px';
  });
 }
 },
 // 关闭弹窗
 close() {
 if(!this.opened) return;
 
 this.closeCls = true;
 setTimeout(() => {
  this.opened = false;
  this.closeCls = false;
  if(JSON.parse(this.shade)) {
  $lockCount--;
  if(!$lockCount) {
  document.body.classList.remove('nt-overflow-hidden');
  }
  }
  if(this.time) {
  $index--;
  }
  this.$emit('input', false);
  this.$emit('close');
  typeof this.onClose === 'function' && this.onClose();
 }, 200);
 },
 shadeClicked() {
 if(JSON.parse(this.shadeClose)) {
  this.close();
 }
 },
 btnClicked(e, index) {
 let btn = this.btns[index];
 if(!btn.disabled) {
  typeof btn.click === 'function' && btn.click(e)
 }
 },
 getZIndex() {
 for(var $idx = parseInt(this.zIndex), $el = document.getElementsByTagName('*'), i = 0, len = $el.length; i < len; i++)
  $idx = Math.max($idx, $el[i].style.zIndex)
 return $idx;
 },
 // 获取弹窗坐标点
 getPos(x, y, ow, oh, winW, winH) {
 let l = (x + ow) > winW ? x - ow : x;
 let t = (y + oh) > winH ? y - oh : y;
 return [l, t];
 }
 },
 }
</script>

通过监听组件传过来的v-model值调用open和close方法。

watch: {
	value(val) {
		const type = val ? 'open' : 'close';
		this[type]();
	},
},

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

另外还支持右键弹窗/长按弹窗自定义插槽内容。

基于Vue.js+Nuxt开发自定义弹出层组件

基于Vue.js+Nuxt开发自定义弹出层组件

<!-- 组件调用 -->
<v-popup v-model="showComponent" xclose xposition="bottom" :shadeClose="false" content="这里是内容信息"
 :btns="[
 {text: '确认', style: 'color:#f60;', click: () => showComponent=false},
 ]"
 @open="handleOpen" @close="handleClose"
>
 <template #content><b style="color:#00e0a1;">当 content 和 自定义插槽 内容同时存在,只显示插槽内容!!!</b></template>
 <!-- <div slot="content">显示自定义插槽内容!</div> -->
 <div style="padding:30px 15px;">
 <img src="https://img.yzcdn.cn/vant/apple-3.jpg" style="width:100%;" @click="handleContextPopup" />
 </div>
</v-popup>

如果想通过函数式调用组件,需要用到Vue.extend扩展构造器来实现。

import Vue from 'vue';
import VuePopup from './popup.vue';
 
let PopupConstructor = Vue.extend(VuePopup);
 
let $instance;
 
let VPopup = function(options = {}) {
 // 同一个页面中,id相同的Popup的DOM只会存在一个
 options.id = options.id || 'nuxt-popup-id';
 $instance = new PopupConstructor({
 propsData: options
 });
 $instance.vm = $instance.$mount();
 
 let popupDom = document.querySelector('#' + options.id);
 if(options.id && popupDom) {
 popupDom.parentNode.replaceChild($instance.$el, popupDom);
 } else {
 document.body.appendChild($instance.$el);
 }
 
 Vue.nextTick(() => {
 $instance.value = true;
 })
 
 return $instance;
}
 
VPopup.install = () => {
 Vue.prototype['$vpopup'] = VPopup;
 Vue.component('v-popup', VuePopup);
}
 
export default VPopup;

这样就实现了在Vue原型 prototype 上挂载 $vpopup 方法及注册 v-popup 组件。

设置圆角及关闭按钮

设置round、xclose即可,另外可以配置xposition来设置关闭按钮位置。

基于Vue.js+Nuxt开发自定义弹出层组件

设置按钮禁用状态

设置disabled: true 可禁用按钮事件。

基于Vue.js+Nuxt开发自定义弹出层组件

Okay,基于Vue.js+Nuxt开发自定义弹出层组件就介绍到这里。目前VPopup正在Nuxt新项目中使用,届时也会分享出来。

最后附上最近两个实例项目

到此这篇关于基于Vue.js+Nuxt开发自定义弹出层组件的文章就介绍到这了,更多相关Vue+Nuxt自定义弹窗内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
初学js插入节点appendChild insertBefore使用方法
Jul 04 Javascript
dtree 网页树状菜单及传递对象集合到js内,动态生成节点
Apr 14 Javascript
快速解决FusionCharts联动的中文乱码问题
Dec 04 Javascript
JS+CSS实现仿触屏手机拨号盘界面及功能模拟完整实例
May 16 Javascript
jQuery原生的动画效果
Jul 10 Javascript
javascript实现动态表头及表列的展现方法
Jul 14 Javascript
理解JavaScript事件对象
Jan 25 Javascript
jQuery获取radio选中项的值实例
Jun 18 Javascript
Vue通过URL传参如何控制全局console.log的开关详解
Dec 07 Javascript
Vue引入sass并配置全局变量的方法
Jun 27 Javascript
vue2.0中set添加属性后视图不能更新的解决办法
Feb 22 Javascript
openlayers4实现点动态扩散
Aug 17 Javascript
IDEA配置jQuery, $符号不再显示黄色波浪线的问题
Oct 09 #jQuery
vue中解决chrome浏览器自动播放音频和MP3语音打包到线上的实现方法
Oct 09 #Javascript
vue实现选中效果
Oct 07 #Javascript
electron踩坑之dialog中的callback解决
Oct 06 #Javascript
electron踩坑之remote of undefined的解决
Oct 06 #Javascript
9个JavaScript日常开发小技巧
Oct 06 #Javascript
详解ES6中class的实现原理
Oct 03 #Javascript
You might like
php操作JSON格式数据的实现代码
2011/12/24 PHP
探讨各种PHP字符串函数的总结分析
2013/06/05 PHP
PHP实现图片上传并压缩
2015/12/22 PHP
golang与php实现计算两个经纬度之间距离的方法
2016/07/22 PHP
根据地区不同显示时间的javascript代码
2007/08/13 Javascript
Microsoft Ajax Minifier 压缩javascript的方法
2010/03/05 Javascript
JavaScript中的一些定位属性[图解]
2010/07/14 Javascript
JavaScript高级程序设计(第3版)学习笔记11 内建js对象
2012/10/11 Javascript
jquery实现图片等比例缩放以及max-width在ie中不兼容解决
2013/03/21 Javascript
javascript打印html内容功能的方法示例
2013/11/28 Javascript
js实现弹出窗口、页面变成灰色并不可操作的例子分享
2014/05/10 Javascript
javascript实现百度地图鼠标滑动事件显示、隐藏
2015/04/02 Javascript
jquery获取css的color值返回RGB的方法
2015/12/18 Javascript
Knockoutjs 学习系列(二)花式捆绑
2016/06/07 Javascript
bootstrap+jQuery实现的动态进度条功能示例
2017/05/25 jQuery
微信小程序loading组件显示载入动画用法示例【附源码下载】
2017/12/09 Javascript
ES6 Object方法扩展的应用实例分析
2019/06/25 Javascript
vscode自定义vue模板的实现
2021/01/27 Vue.js
python条件变量之生产者与消费者操作实例分析
2017/03/22 Python
Python在信息学竞赛中的运用及Python的基本用法(详解)
2017/08/15 Python
ubuntu环境下python虚拟环境的安装过程
2018/01/07 Python
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
Selenium chrome配置代理Python版的方法
2018/11/29 Python
OpenCV+Python识别车牌和字符分割的实现
2019/01/31 Python
Django 自定义权限管理系统详解(通过中间件认证)
2020/03/11 Python
详解利用css3的var()实现运行时改变scss的变量值
2021/03/02 HTML / CSS
html5 兼容IE6结构的实现代码
2012/05/14 HTML / CSS
HTML5新增属性data-*和js/jquery之间的交互及注意事项
2017/08/08 HTML / CSS
马来西亚在线药房:RoyalePharma
2019/12/01 全球购物
会计专业个人求职信范文
2014/01/08 职场文书
安全检查验收制度
2014/01/12 职场文书
承诺保证书格式
2015/02/28 职场文书
公司捐书倡议书
2015/04/27 职场文书
SQL实现LeetCode(196.删除重复邮箱)
2021/08/07 MySQL
HTML中的表单元素介绍
2022/02/28 HTML / CSS
“鬼灭之刃”热度不减,其成功背后的原因是什么?
2022/03/22 日漫