详解用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 相关文章推荐
Extjs TriggerField在弹出窗口显示不出问题的解决方法
Jan 08 Javascript
js png图片(有含有透明)在IE6中为什么不透明了
Feb 07 Javascript
jquery 回车事件实现代码
Aug 23 Javascript
EASYUI TREEGRID异步加载数据实现方法
Aug 22 Javascript
js正文内容高亮效果的实现方法
Jun 30 Javascript
JavaScript 消息框效果【实现代码】
Apr 27 Javascript
Node.js connect ECONNREFUSED错误解决办法
Sep 15 Javascript
基于vue2.0+vuex+localStorage开发的本地记事本示例
Feb 28 Javascript
详解原生js实现offset方法
Jun 15 Javascript
深入理解基于vue-cli的vuex配置
Jul 24 Javascript
让Vue也可以使用Redux的方法
May 23 Javascript
解决vue attr取不到属性值的问题
Sep 18 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
极典R601SW收音机
2021/03/02 无线电
php实现把url转换迅雷thunder资源下载地址的方法
2014/11/07 PHP
详解php几行代码实现CSV格式文件输出
2017/07/01 PHP
php无限级分类实现评论及回复功能
2019/02/18 PHP
Javascript - HTML的request类
2006/07/15 Javascript
javascript脚本编程解决考试分数统计问题
2008/10/18 Javascript
深入理解JS中的变量及作用域、undefined与null
2014/03/04 Javascript
js中的onchange和onpropertychange (onchange无效的解决方法)
2014/03/08 Javascript
13 款最热门的 jQuery 图像 360 度旋转插件推荐
2014/12/09 Javascript
js实现从右向左缓缓浮出网页浮动层广告的方法
2015/05/09 Javascript
JS实现兼容各种浏览器的获取选择文本的方法【测试可用】
2016/06/21 Javascript
全面了解构造函数继承关键apply call
2016/07/26 Javascript
微信小程序 教程之注册程序
2016/10/17 Javascript
jquery中用函数来设置css样式
2016/12/22 Javascript
jQuery中的deferred对象和extend方法详解
2017/05/08 jQuery
详解在Angular项目中添加插件ng-bootstrap
2017/07/04 Javascript
VueCli3.0中集成MockApi的方法示例
2019/07/05 Javascript
python中mechanize库的简单使用示例
2014/01/10 Python
Python and、or以及and-or语法总结
2015/04/14 Python
python3.5使用tkinter制作记事本
2016/06/20 Python
详解Python计算机视觉 图像扭曲(仿射扭曲)
2019/03/27 Python
python交互模式下输入换行/输入多行命令的方法
2019/07/02 Python
使用Python实现正态分布、正态分布采样
2019/11/20 Python
python实现名片管理器的示例代码
2019/12/17 Python
css3实例教程 一款纯css3实现的环形导航菜单
2014/10/20 HTML / CSS
英国时尚女装购物网站:Missguided
2018/08/23 全球购物
Nike香港官网:Nike HK
2019/03/23 全球购物
Lookfantastic阿联酋官网:英国知名美妆护肤购物网站
2020/05/26 全球购物
意大利单身交友网站:Meetic
2020/07/12 全球购物
Python里面search()和match()的区别
2016/09/21 面试题
父母对孩子说的话
2014/04/12 职场文书
超市促销活动总结
2014/07/01 职场文书
2014年售后服务工作总结
2014/11/18 职场文书
酒店前台接待岗位职责
2015/04/02 职场文书
初一军训感言
2015/08/01 职场文书
2016高考冲刺决心书
2015/09/23 职场文书