基于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 相关文章推荐
jQuery Dialog 弹出层对话框插件
Aug 09 Javascript
Jquery Ajax解析XML数据(同步及异步调用)简单实例
Feb 12 Javascript
jquery实现叠层3D文字特效代码分享
Aug 21 Javascript
js中字符型和数值型数字的互相转化方法(必看)
Apr 25 Javascript
electron demo项目npm install安装失败的解决方法
Feb 06 Javascript
JavaScript函数式编程(Functional Programming)组合函数(Composition)用法分析
May 22 Javascript
详解vue-video-player使用心得(兼容m3u8)
Aug 23 Javascript
layer关闭弹出窗口触发表单提交问题的处理方法
Sep 25 Javascript
es6中Promise 对象基本功能与用法实例分析
Feb 23 Javascript
jQuery实现颜色打字机的完整代码
Mar 19 jQuery
你准备好迎接vue3.0了吗
Apr 28 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文件向另一个地址post数据,不用表单和隐藏的变量的
2007/03/06 PHP
php 中的str_replace 函数总结
2007/04/27 PHP
php session的锁和并发
2016/01/22 PHP
PHP+mysql+ajax轻量级聊天室实现方法详解
2016/10/17 PHP
PHP封装的数据库模型Model类完整示例【基于PDO】
2019/03/14 PHP
Yii框架安装简明教程
2020/05/15 PHP
Javascript 网页黑白效果实现代码(兼容IE/FF等)
2010/04/23 Javascript
基于JavaScript实现继承机制之调用call()与apply()的方法详解
2013/05/07 Javascript
为开发者准备的10款最好的jQuery日历插件
2014/02/04 Javascript
nodejs之请求路由概述
2014/07/05 NodeJs
javascript bom是什么及bom和dom的区别
2015/11/26 Javascript
详解JavaScript中localStorage使用要点
2016/01/13 Javascript
JavaScript 对象字面量讲解
2016/06/06 Javascript
详解vue-validator(vue验证器)
2017/01/16 Javascript
jQuery使用EasyUi实现三级联动下拉框效果
2017/03/08 Javascript
详解node.js搭建代理服务器请求数据
2017/04/08 Javascript
详解用webpack2搭建angular2的项目
2017/06/22 Javascript
React Native实现地址挑选器功能
2017/10/24 Javascript
详解小程序原生使用ES7 async/await语法
2018/08/06 Javascript
vue实现登录页面的验证码以及验证过程解析(面向新手)
2019/08/02 Javascript
node.js中 mysql 增删改查操作及async,await处理实例分析
2020/02/11 Javascript
Swiper实现导航栏滚动效果
2020/10/16 Javascript
Vue使用路由钩子拦截器beforeEach和afterEach监听路由
2020/11/16 Javascript
[01:16:01]VGJ.S vs Mski Supermajor小组赛C组 BO3 第一场 6.3
2018/06/04 DOTA
Python 3实战爬虫之爬取京东图书的图片详解
2017/10/09 Python
python的pip安装以及使用教程
2018/09/18 Python
python print出共轭复数的方法详解
2019/06/25 Python
numpy按列连接两个维数不同的数组方式
2019/12/06 Python
利用Python实现朋友圈中的九宫格图片效果
2020/09/03 Python
领导党性分析材料
2014/02/15 职场文书
2014年大学生党员评议表自我评价
2014/09/20 职场文书
干部作风建设年活动剖析材料
2014/10/23 职场文书
2019年汽车租赁合同范本!
2019/08/12 职场文书
MySQL慢查询优化解决问题
2022/03/17 MySQL
python使用opencv对图像添加噪声(高斯/椒盐/泊松/斑点)
2022/04/06 Python
SpringCloud Function SpEL注入漏洞分析及环境搭建
2022/04/08 Java/Android