写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 的弹框的更多相关文章

  1. 【jQuery学习】写一个简单的弹框页面,火狐浏览器有弹框,但IE8没有弹框的原因?

    我也是刚学习jQuery,就从官网上下载了jQuery的包,版本是3.2.1 代码 如下: <!DOCTYPE html> <html> <head> <me ...

  2. 写一个vue组件

    写一个vue组件 我下面写的是以.vue结尾的单文件组件的写法,是基于webpack构建的项目.如果还不知道怎么用webpack构建一个vue的工程的,可以移步到vue-cli. 一个完整的vue组件 ...

  3. 写一个Vue loading 插件

    什么是vue插件? 从功能上说,插件是为Vue添加全局功能的一种机制,比如给Vue添加一个全局组件,全局指令等: 从代码结构上说,插件就是一个必须拥有install方法的对象,这个方法的接收的第一个参 ...

  4. 面试题:你能写一个Vue的双向数据绑定吗?

    在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫myVue吧.结合注释,希望 ...

  5. vue中超简单的方法实现点击一个按钮出现弹框,点击弹框外关闭弹框

    效果图展示: View层 <template> <div> <div class="mask" v-if="showModal" ...

  6. 仿写confirm和alert弹框

    在工作中,我们常常会遇到原生的样式感觉比较丑,又和我们做的项目风格不搭.于是就有了仿写原生一些组件的念头,今天我就带大家仿写一下confirm和alert样式都可以自己修改. 有些的不好的地方请指出来 ...

  7. vue定时器+弹框 跳到登陆页面

    1.做一个请求拦截,并弹框提示几秒后,跳转到登陆首页或是点击确定之后直接跳转拦截用了this.$axios.interceptors.response页面上的弹框组件用了vux的组件vux地址:htt ...

  8. CreateProcessAsUser,C#写的windows服务弹框提示消息或者启动子进程

    服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分.我们可以把服务想像成一种特殊的应用程序,它随系统的“开启-关闭”而“开始-停止”其工作内容,在这期间无需任何 ...

  9. vue自定义弹框

    vue 全局自定义简单弹框 https://www.jianshu.com/p/1307329aa09e https://www.cnblogs.com/crazycode2/p/7907905.ht ...

随机推荐

  1. Java Spring Boot VS .NetCore (七) 配置文件

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  2. 使用apt-get安装相关的软件时,不能Fetch,现在更新为国内的源!

    我使用的是中国科技大学的树莓派的软件源,测试可以使用(更新时间:2018年7月15日) deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ jessie ...

  3. python实现Hbase

    1. 下载thrift 作用:翻译python语言为hbase语言的工具 2. 运行时先启动hbase 再启动thrift,最后在pycharm中通过happybase包连接hbase 在hbase目 ...

  4. 移动端click事件清除

    http://blog.csdn.net/zfy865628361/article/details/49512095

  5. 2017-2018 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2017)

    A. Cakey McCakeFace 按题意模拟即可. #include<stdio.h> #include<iostream> #include<string.h&g ...

  6. centos7.4安装redis

    参考连接 https://blog.csdn.net/qq_19399235/article/details/78313633/

  7. win10安装ubuntu16.04双系统历程

    目录 win10安装ubuntu16.04双系统 历程 安装时间 安装准备 安装过程 其他问题 win10安装ubuntu16.04双系统 历程 安装时间 2018.11.30 安装准备 u盘(格式化 ...

  8. 100837D

    囤了一个星期..今天看了下vj上 sysuteam7 三年半之前的代码.. 深刻地认识到了自己智商不足的问题. 先求出来每个点对中心的偏移量.确实是乱序的,但是我们可以极角排序,这样一定是一个循环移位 ...

  9. 关于finally代码块是否一定被执行的问题

    一般来说,只要执行了try语句,finally就会执行 但是,有以下几种情况需要特殊考虑 具体例子看链接  点击这里 第一点 try代码块没有被执行,意思就是错误在try代码块之前就发生了. 第二点 ...

  10. 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 ...