如何优雅的写一个Vue 的弹框
写Vue或者是react 都会遇见弹框的问题。也尝试了多种办法来写弹框,一直都不太满意,今天特地看了一下 Element UI 的源码,模仿着写了一个简易版。
大概有一下几个问题:
1、弹框的层级问题,如果在嵌套的组件里面使用了弹框,可能会出现弹框的层级不够高
2、弹框的函数调用方式
首先第一点:弹框的层级
如果将弹框放置在最外层,body下面。就不会有层级问题。
第二点:弹框的函数调用
首先我们可以思考,将组件的实例拿到,然而初学的时候好像只有 通过 refs 能拿到组件的对象,然后调用显示隐藏
其实我们可以通过 VUE.extend 这个函数,对组件进行初始化,然后可以拿到 组件对象
对于 Vue.extend 不太清楚的,建议自己去百度学习一下。
下面给出弹框的代码: alert.vue 文件下面
<template>
<div class="_alert" v-show="visible">
<div class="wind-alert">
<div class="wind-alert-bg"></div>
<div class="wind-alert-dialog animate-scale">
<div class="wind-alert-title">{{title}}</div>
<div class="wind-alert-content">{{content}}</div>
<div class="wind-alert-btn" @click="close">{{btn}}</div>
</div>
</div>
</div>
</template>
<script>
export default {
name:"rule_alert",
data() {
return {
title: '提示',
content: '',
btn: '确定',
visible:false
}
},
methods: {
close() {
this.visible = false;
this._promise && this._promise.resolve()
}
},
watch: {
'$route' () {
this.close();
}
}
}
</script>
<style>
.wind-alert-dialog {
top: 30%;
width: 80%;
left: 50%;
opacity: 1;
position: fixed;
margin-left: -40%;
font-size: 14px;
text-align: center;
font-family: 'Microsoft Yahei';
background: #FFFFFF;
border-radius: 8px;
z-index: 999999999;
box-sizing: content-box;
} .wind-alert-bg {
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.3;
display: block;
position: fixed;
z-index: 999999998;
background-color: #000000;
} .wind-alert-title {
font-size: 17px;
padding: 20px 5px 0;
} .wind-alert-content {
padding: 5px 15px 20px 15px;
border-bottom: 1px solid #ededed;
} .wind-alert-btn {
color: #0582cd;
font-size: 15px;
line-height: 40px;
font-weight: bold;
} .animate-scale {
animation-name: scale;
animation-duration: 0.375s;
} @keyframes scale {
0%{
transform: scale(0);
}
100% {
transform: scale(1);
}
}
</style>
接下来,就是将这个组件,进行初始化,并且注入一些自己的方法和属性
这个地方的注入,是一个公共的方法,后面可以引入其他类型的弹框,比如 comfirm 类型的
新建 plugin.js
import Alert from "@/components/alert"; import Vue from "vue"; //原始组件
var components = {
Alert:Alert
} var instance = {}; //缓存组件的实例
var Ruler = {}; //组件的集合
var body = document.body || document.documentElement;
var root = document.createElement("div");
body.appendChild(root); //初始化构造vue组件,并且注入自己的代码
const initComponents = function(type,options){
options = options || {};
type = type || '';
if(components[type]){
if(!instance[type]){
//避免重复的初始化
var div = document.createElement('div');
root.appendChild(div);
const MessageBoxConstructor = Vue.extend(components[type]); instance[type] = new MessageBoxConstructor({
el: div
});
}
var ins = instance[type];
//复制属性
for(var i in options){
ins[i] = options[i];
}
Vue.nextTick(()=>{
ins.visible = true;
})
return new Promise(function(resolve,reject){
//注入当前的 promise
ins._promise = {
resolve,
reject
};
}).finally(()=>{
//ins.visible = false;
//可以在这里监听,不管结果如何,最后执行一段代码
});
}else{
return Promise.reject("组件不存在");
};
}
//开始注册组件 var Ruler = {}; //组件的集合 //主动关闭某个组件弹窗 type 组件类型名称, methods false 取消关闭, true 确认关闭
Ruler.closeComponents = function (type,methods) {
if(instance[type] && instance[type]._promise){
if(methods){
instance[type]._promise.resolve();
}else{
instance[type]._promise.reject();
}
instance[type].visible = false;
}
} //对弹出组件的初始化处理
function popupHandle(i,options){
if(typeof options == "string"){
options = {
msg: options
}
}
return initComponents(i,options);
} for(var i in components){
Ruler[i] = popupHandle.bind(components[i],i);
}
export default{
install(Vue){
Vue.prototype.$Ruler = Ruler;
}
}
接下来就是在 main.js 里面引入了:
import plugin from "@/plugin/plugin";
Vue.use(plugin);
然后在任意的地方使用
this.$Ruler.Alert("这是一个提示").then((ret)=>{
console.log("then",ret);
}).catch((e)=>{
console.log("catch",e);
});
注意: Vue.extend 初始化的组件,其内部 this.$router 是 undefined ,还有 this.$store 也是,可以直接import 后使用,
也可以 在组件里面 导入 router 之后,和data 平级,写一个router,,,,这样,组件在传入 Vue.extend的时候,就能够访问到 this.$router 了

或者在 Vue.extend 以后 new 的时候加入 router ,如:
instance[type] = new MessageBoxConstructor({
el: div,
router:router
});
其原理在于: Vue.extend 函数,返回的一个继承了 Vue 的子类。
也就是说
new MessageBoxConstructor 的时候,等同于 new Vue
如何优雅的写一个Vue 的弹框的更多相关文章
- 【jQuery学习】写一个简单的弹框页面,火狐浏览器有弹框,但IE8没有弹框的原因?
我也是刚学习jQuery,就从官网上下载了jQuery的包,版本是3.2.1 代码 如下: <!DOCTYPE html> <html> <head> <me ...
- 写一个vue组件
写一个vue组件 我下面写的是以.vue结尾的单文件组件的写法,是基于webpack构建的项目.如果还不知道怎么用webpack构建一个vue的工程的,可以移步到vue-cli. 一个完整的vue组件 ...
- 写一个Vue loading 插件
什么是vue插件? 从功能上说,插件是为Vue添加全局功能的一种机制,比如给Vue添加一个全局组件,全局指令等: 从代码结构上说,插件就是一个必须拥有install方法的对象,这个方法的接收的第一个参 ...
- 面试题:你能写一个Vue的双向数据绑定吗?
在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫myVue吧.结合注释,希望 ...
- vue中超简单的方法实现点击一个按钮出现弹框,点击弹框外关闭弹框
效果图展示: View层 <template> <div> <div class="mask" v-if="showModal" ...
- 仿写confirm和alert弹框
在工作中,我们常常会遇到原生的样式感觉比较丑,又和我们做的项目风格不搭.于是就有了仿写原生一些组件的念头,今天我就带大家仿写一下confirm和alert样式都可以自己修改. 有些的不好的地方请指出来 ...
- vue定时器+弹框 跳到登陆页面
1.做一个请求拦截,并弹框提示几秒后,跳转到登陆首页或是点击确定之后直接跳转拦截用了this.$axios.interceptors.response页面上的弹框组件用了vux的组件vux地址:htt ...
- CreateProcessAsUser,C#写的windows服务弹框提示消息或者启动子进程
服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分.我们可以把服务想像成一种特殊的应用程序,它随系统的“开启-关闭”而“开始-停止”其工作内容,在这期间无需任何 ...
- vue自定义弹框
vue 全局自定义简单弹框 https://www.jianshu.com/p/1307329aa09e https://www.cnblogs.com/crazycode2/p/7907905.ht ...
随机推荐
- Java Spring Boot VS .NetCore (七) 配置文件
Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...
- 使用apt-get安装相关的软件时,不能Fetch,现在更新为国内的源!
我使用的是中国科技大学的树莓派的软件源,测试可以使用(更新时间:2018年7月15日) deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ jessie ...
- python实现Hbase
1. 下载thrift 作用:翻译python语言为hbase语言的工具 2. 运行时先启动hbase 再启动thrift,最后在pycharm中通过happybase包连接hbase 在hbase目 ...
- 移动端click事件清除
http://blog.csdn.net/zfy865628361/article/details/49512095
- 2017-2018 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2017)
A. Cakey McCakeFace 按题意模拟即可. #include<stdio.h> #include<iostream> #include<string.h&g ...
- centos7.4安装redis
参考连接 https://blog.csdn.net/qq_19399235/article/details/78313633/
- win10安装ubuntu16.04双系统历程
目录 win10安装ubuntu16.04双系统 历程 安装时间 安装准备 安装过程 其他问题 win10安装ubuntu16.04双系统 历程 安装时间 2018.11.30 安装准备 u盘(格式化 ...
- 100837D
囤了一个星期..今天看了下vj上 sysuteam7 三年半之前的代码.. 深刻地认识到了自己智商不足的问题. 先求出来每个点对中心的偏移量.确实是乱序的,但是我们可以极角排序,这样一定是一个循环移位 ...
- 关于finally代码块是否一定被执行的问题
一般来说,只要执行了try语句,finally就会执行 但是,有以下几种情况需要特殊考虑 具体例子看链接 点击这里 第一点 try代码块没有被执行,意思就是错误在try代码块之前就发生了. 第二点 ...
- CentOS启动docker1.13失败(Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.)
一.启动失败 1.启动docker [root@localhost ~]# systemctl start docker Job for docker.service failed because t ...