详解用vue编写弹出框组件


Posted in Javascript onJuly 04, 2017

前言

最近研究了用vue编写弹出框的组件,发现其实这里面的门道还是有很多的。这篇文完全是用来记录总结下最近的学习成果,同时也希望能够帮得上正在学习纠结的你~ps:本文假设你已经了解vue2.0相关框架,因此适合有一定vue2.0基础的同学阅读。

设计组件的思考

其实单纯的编写一个弹出框组件并不难,写一个模板,然后用v-if或者v-show指令还控制组件的出现与消失。真正困扰我的是,这个组件的调用方式,这个问题纠结了我好久。

调研了下资料,有些人建议,直接把组件标签插进模板中,然后通过直接控制组件的显示隐藏来控制组件。这样写有好处,就是结构清晰,一目了然,人家一看你的代码就知道你这个页面可能会有弹出框,并且编写的组件就更容易,只需关注内部方法就好了,也不存在事件调用的困扰,维护起来也特别容易。但是缺点也很明显,如果有多个弹窗,并且不知道会有几个弹窗的情况下,感觉就不太好做,并且这种提前写模板的形式,难免会在不弹窗的时候要下载一些js文件,有可能会造成性能浪费。

也有些人建议,在写好的弹出框组件之外再做一层封装,通过动态调用的方式来控制弹出框的显示与隐藏。这样写的好处是不用事先在模板里面写好该组件的标签,只需要在想调用的地方调用下该组件,就实现了按需使用的目的,符合之前传统前端框架的编码习惯。缺点就是感觉代码写起来比较复杂,层层嵌套,并且感觉这个与MVVM模式的状态驱动界面的思想相违背。

于是我天秤座的纠结病犯了,在选择哪种技术方案的问题上,思考了很久。但是网上搜了很多,发现还是后一种实现方法用的人比较多。后来我又研究了了elementUI和iView的弹出框组件,他们也是沿用的后一种方法,想了一下后一种方法虽然代码易读性不强,但是它真正模拟了浏览器默认的alert事件,在用户需要的地方来调用,一方面节省了代码量,另一方面也很容易解决多个弹窗的情况。最后还是决定用这种模式写一个简单的弹出框组件。主要是体会这其中的机理。废话不多说,来上干货了。有啥不对的地方还请大家多多指教。(ps:对于天秤座的我,虽然选择了后一种方法,但是内心还是钟爱第一种方法,并且后一种方法并没有足够的理由说服我呀,不知道哪位有识之士能够帮忙点醒一下我,晚辈感激不尽)。

alert组件设计

单独的设计alert弹出框的逻辑是很简单的,我就直接上代码了:

 

<template>
<transition name='fade'>
 <div class="alert" v-if="showAlert">
  <div class="wrap">
   <div class="head">{{title}}</div>
   <div class="body">
    <slot>
     <p>{{message}}</p>
    </slot>
   </div>
   <div class="foot">
    <div v-if="type === 'confirm'">
     <button class="btn-base" @click="sure">确定</button>
     <button class="btn-gray" @click="cancel">取消</button>
    </div>
    <div v-else-if="type === 'inform'">
     <button class="btn-base" @click="cancel">知道了</button>
    </div>
   </div>
  </div>
 </div>
</transition>
</template>
<script>
export default {
 name: 'alert',
 data() {
  return {
   showAlert: false,
  };
 },
 props: {
  title: {
   type: String,
   default: '提示',
  },
  message: {
   type: String,
  },
  type: { // 可以有confirm, 和inform两个类型
   type: String,
   default: 'confirm',
   validator(value) {
    return value === 'confirm' || value === 'inform';
   },
  },
  sureBtn: {
   type: Function,
  },
  cancelBtn: {
   type: Function,
  },
  context: {
   type: Object,
  },
 },
 methods: {
  cancel() {
   if (this.cancelBtn) {
    this.cancelBtn.apply(this.context);
   }
   this.close();
  },
  sure() {
   if (this.sureBtn) {
    this.sureBtn.apply(this.context);
   }
   this.close();
  },
  show() {
   this.showAlert = true;
  },
  close() {
   this.showAlert = false;
  },
 },
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang='scss'>
.alert {
 position: fixed;
 top: 0;
 left: 0;
 right: 0;
 bottom: 0;
 background: rgba(0,0,0, 0.8);
 z-index: 1000;
 transition: all .3s ease-in-out;
}
.wrap {
 position: absolute;
 z-index: 1002;
 min-width: 400px;
 background: #fff;
 left: 50%;
 top: 50%;
 transform: translate(-50%, -50%);
 border-radius: 4px;
}
.head {
 height: 40px;
 line-height: 40px;
 border-bottom: 1px solid #dedede;
 padding-left: 10px;
 color: #333;
}
.body {
 padding: 40px 20px;
 text-align: center;
}
.foot {
 height: 50px;
 text-align: center;
 button {
  margin-right: 20px;
  &:last-child {
   margin-right: 0;
  }
 }
}
</style>

这里只是写了简单的功能,并没有考虑更复杂的情况,比如按钮颜色定制,大小定制,z-index层级的考虑,遮罩层的统一管理等等,只是为了掌握编写弹出框的主要思想,所以没有写太多的情况。这里只细分了是确认框还是通知框,可以定制弹出框的内容、标题等一些简单的常规操作。

其实这个组件写好,就可以在页面用起来了,直接在对应页面插入这段,可以也可以用:

<!--template-->
<button @click="showAlert">点我</button>
<alert ref="alert">我是一个确认框</alert>
<!--javascript-->
...
methods: {
  showAlert() {
    this.$refs.alert.show();
  }
}
...

当然,如果真要这么用,这个组件还是需要修改一些东西的,比如事件抛出,当点击确定或者取消按钮的时候,需要emit对应的事件,以提供给父组件捕获,并做相应的处理。

动态插入到页面中

为了能让组件动态的插入到页面中,需要对上面的组件进行封装,利用Vue.extend机制,可以轻松的做到这种封装,直接上代码:

import Vue from 'vue';
import alert from './alert';
const AlertConstructor = Vue.extend(alert);
const div = document.createElement('div');
AlertConstructor.show = (options) => {
 document.body.appendChild(div);
 options.type = 'inform';
 const propsData = Object.assign({}, options);
 const alertInstance = new AlertConstructor({
  propsData,
 }).$mount(div);
 alertInstance.show();
};
AlertConstructor.confirm = (options) => {
 document.body.appendChild(div);
 options.type = 'confirm';
 const propsData = Object.assign({}, options);
 const alertInstance = new AlertConstructor({
  propsData,
 }).$mount(div);
 alertInstance.show();
};
export default AlertConstructor;

这里,show对应的是通知框,confirm对应的是确认框。我知道这种封装有点简单了,有很多情况没有考虑,比如有多个弹出框时的处理等。这里只是做了简单的封装,为的就是让大家明白此种封装主要思路是什么。

总结

这篇文章仅仅是对自己这几天摸索弹出框组件问题的一个简短的总结与思考。可能还不是很成熟,当做抛砖引玉吧,欢迎大家多多提意见。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
网页前端优化之滚动延时加载图片示例
Jul 13 Javascript
简介JavaScript中的sub()方法的使用
Jun 08 Javascript
实例剖析AngularJS框架中数据的双向绑定运用
Mar 04 Javascript
jQuery悬停文字提示框插件jquery.tooltipster.js用法示例【附demo源码下载】
Jul 19 Javascript
JS判断是否在微信浏览器打开的简单实例(推荐)
Aug 24 Javascript
ion content 滚动到底部会遮住一部分视图的快速解决方法
Sep 06 Javascript
Angular 1.x个人使用的经验小结
Jul 19 Javascript
JavaScript门面模式详解
Oct 19 Javascript
详解webpack3编译兼容IE8的正确姿势
Dec 21 Javascript
vue中当图片地址无效的时候,显示默认图片的方法
Sep 18 Javascript
jQuery层叠选择器用法实例分析
Jun 28 jQuery
Vue中使用better-scroll实现轮播图组件
Mar 07 Javascript
使用vue构建一个上传图片表单
Jul 04 #Javascript
vue-resource 拦截器(interceptor)的使用详解
Jul 04 #Javascript
JavaScript在控件上添加倒计时功能的实现代码
Jul 04 #Javascript
JavaScript异步上传图片文件的实例代码
Jul 04 #Javascript
详解vue-router和vue-cli以及组件之间的传值
Jul 04 #Javascript
详解Angular.js中$http拦截器的介绍及使用
Jul 04 #Javascript
详解vue-cli 脚手架项目-package.json
Jul 04 #Javascript
You might like
php中将图片gif,jpg或mysql longblob或blob字段值转换成16进制字符串
2011/08/23 PHP
基于php 随机数的深入理解
2013/06/05 PHP
php5.3 不支持 session_register() 此函数已启用的解决方法
2013/11/12 PHP
php实现的返回数据格式化类实例
2014/09/22 PHP
php输出xml必须header的解决方法
2014/10/17 PHP
详解PHP编码转换函数应用技巧
2016/10/22 PHP
thinkphp整合微信支付代码分享
2016/11/24 PHP
扩展jQuery对象时如何扩展成员变量具体怎么实现
2014/04/25 Javascript
技术男用来对妹子表白的百度首页
2014/07/23 Javascript
深入分析jquery解析json数据
2014/12/09 Javascript
jQuery表单验证功能实例
2015/08/28 Javascript
Vue 组件(component)教程之实现精美的日历方法示例
2018/01/08 Javascript
完美解决axios跨域请求出错的问题
2018/02/05 Javascript
深入Node TCP模块的理解
2019/03/13 Javascript
JavaScript如何实现监听键盘输入和鼠标监点击
2020/07/20 Javascript
[00:34]TI7不朽珍藏III——地穴编织者不朽展示
2017/07/15 DOTA
Python sys.path详细介绍
2013/10/17 Python
Python编程之黑板上排列组合,你舍得解开吗
2017/10/30 Python
Python中pillow知识点学习
2018/04/30 Python
python添加菜单图文讲解
2019/06/04 Python
TensorFLow 不同大小图片的TFrecords存取实例
2020/01/20 Python
Python3和PyCharm安装与环境配置【图文教程】
2020/02/14 Python
python3.6环境下安装freetype库和基本使用方法(推荐)
2020/05/10 Python
Python爬虫实现百度翻译功能过程详解
2020/05/29 Python
python 服务器运行代码报错ModuleNotFoundError的解决办法
2020/09/16 Python
html5的canvas方法使用指南
2014/12/15 HTML / CSS
VELTRA台湾:世界自由行专家
2017/08/15 全球购物
护理个人求职信范文
2014/01/08 职场文书
入党积极分子介绍信
2014/01/17 职场文书
金融管理应届生求职信
2014/02/20 职场文书
广告学专业求职信
2014/06/19 职场文书
计划生育证明格式范本
2014/09/12 职场文书
社区党建工作汇报材料
2014/10/27 职场文书
秦兵马俑导游词
2015/02/02 职场文书
网络研修随笔感言
2015/11/18 职场文书
python读取并查看npz/npy文件数据以及数据显示方法
2022/04/14 Python