详解用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 相关文章推荐
给Flash加一个超链接(推荐使用透明层)兼容主流浏览器
Jun 09 Javascript
jQuery插件expander实现图片翻转特效
May 21 Javascript
Jquery ajax 同步阻塞引起的UI线程阻塞问题
Nov 17 Javascript
使用jQuery在移动页面上添加按钮和给按钮添加图标
Dec 04 Javascript
js 求时间差的实现代码
Apr 26 Javascript
实用又漂亮的BootstrapValidator表单验证插件
May 30 Javascript
javascript 组合按键事件监听实现代码
Feb 21 Javascript
vue-cli单页应用改成多页应用配置详解
Jul 14 Javascript
webpack进阶——缓存与独立打包的用法
Aug 02 Javascript
Vue 去除路径中的#号
Apr 19 Javascript
详解element-ui日期时间选择器的日期格式化问题
Apr 08 Javascript
vue项目使用高德地图的定位及关键字搜索功能的实例代码(踩坑经验)
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 编写的 25个游戏脚本
2009/05/11 PHP
php获取本周开始日期和结束日期的方法
2015/03/09 PHP
浅谈PHP中output_buffering
2015/07/13 PHP
验证token、回复图文\文本、推送消息的实用微信类php代码
2016/06/28 PHP
总结PHP如何获取当前主机、域名、网址、路径、端口和参数等
2016/09/09 PHP
使用jQuery向asp.net Mvc传递复杂json数据-ModelBinder篇
2010/05/07 Javascript
JavaScript中的细节分析
2012/06/30 Javascript
js浏览器本地存储store.js介绍及应用
2014/05/13 Javascript
js实现文本框只允许输入数字并限制数字大小的方法
2015/08/19 Javascript
探究Javascript模板引擎mustache.js使用方法
2016/01/26 Javascript
JS组件Bootstrap ContextMenu右键菜单使用方法
2016/04/17 Javascript
BootStrap智能表单实战系列(十一)级联下拉的支持
2016/06/13 Javascript
json数据传到前台并解析展示成列表的方法
2018/08/06 Javascript
vue路由对不同界面进行传参及跳转的总结
2019/04/20 Javascript
Js实现复选框的全选、全不选反选功能代码实例
2020/02/28 Javascript
Js Snowflake(雪花算法)生成随机ID的实现方法
2020/08/26 Javascript
高性能web服务器框架Tornado简单实现restful接口及开发实例
2014/07/16 Python
Windows系统下多版本pip的共存问题详解
2017/10/10 Python
简述Python2与Python3的不同点
2018/01/21 Python
Python面向对象程序设计构造函数和析构函数用法分析
2019/04/12 Python
pytorch 实现张量tensor,图片,CPU,GPU,数组等的转换
2020/01/13 Python
python开发实例之Python的Twisted框架中Deferred对象的详细用法与实例
2020/03/19 Python
Python列表去重复项的N种方法(实例代码)
2020/05/12 Python
Godiva巧克力英国官网:比利时歌帝梵巧克力
2018/08/28 全球购物
新郎父亲婚宴答谢词
2014/01/11 职场文书
高一化学教学反思
2014/02/05 职场文书
经销商订货会主持词
2014/03/27 职场文书
程序员求职信
2014/04/16 职场文书
市政工程技术专业自荐书
2014/07/06 职场文书
罚款通知怎么写
2015/04/22 职场文书
2015年幼儿园班主任工作总结
2015/05/12 职场文书
党员证明信
2015/06/19 职场文书
2015年度学校应急管理工作总结
2015/10/22 职场文书
CSS3 实现NES游戏机的示例代码
2021/04/21 HTML / CSS
Mysql文件存储图文详解
2021/06/01 MySQL
关于 Python json中load和loads区别
2021/11/07 Python