Vue组件系列开发之模态框


Posted in Javascript onApril 18, 2019

项目基础工程文件是使用vue-cli3.0搭建的,这里不过多介绍。开发Vue组件系列之模态框,主要有标题、内容、定时器、按钮文案、按钮事件回调、遮罩层这些可配置项。本次开发得组件是本系列的第一个组件,后期也会有更多系列教程推出。

使用命令行

$ Vue create echi-modal
$ cd echi-modal
$ npm install
$ npm run serve
$ npm run build
$ npm run lint

添加vue.config.js文件,配置如下

const path = require("path");

function resolve(dir) {
 return path.join(__dirname, dir);
}

module.exports = {
 // 基本路径
 publicPath: "./",
 // eslint-loader 是否在保存的时候检查
 lintOnSave: false,
 // webpack配置
 // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
 chainWebpack: config => {
 config.resolve.alias
  .set("@", resolve("src"))
 },
 // 生产环境是否生成 sourceMap 文件
 productionSourceMap: false,
 // css相关配置
 css: {
 // 是否使用css分离插件 ExtractTextPlugin
 extract: true,
 // 开启 CSS source maps?
 sourceMap: false,
 // css预设器配置项
 loaderOptions: {},
 // 启用 CSS modules for all css / pre-processor files.
 modules: false
 },
 // use thread-loader for babel & TS in production build
 // enabled by default if the machine has more than 1 cores
 parallel: require("os").cpus().length > 1,
 devServer: {
 port: 9595, // 端口号
 open: true, // 自动开启浏览器
 compress: true, // 开启压缩
 overlay: {
  warnings: true,
  errors: true
 }
 }
};

项目结构

├── src       # 项目源码。开发的时候代码写在这里。
│ ├── components     # 组件目录
| | |--EchiModal    # 模态框组件
│ ├── App.vue     # 项目根视图
│ ├── main.js     # 程序主入口

部分截图

Vue组件系列开发之模态框

Vue组件系列开发之模态框

Vue组件系列开发之模态框

modal组件模板

使用 transition 可以为组件添加动效;对应的组件模板内容如下

<template>
 <transition name="toggle">
 <section class="modal" v-show="visible">
  <div class="modal-mask" v-show="showMask" @click="clickMask"></div>
  <section class="modal-content modal-center" :style="contentStyle">
  <header class="modal-header" :class="{ 'modal-plain': plain }" v-if="showHeader">
   <slot name="header">{{ title }}</slot>
   <span class="closed" v-if="showClose" @click.stop="onClose">
   关闭
   </span>
  </header>
  <main class="modal-body">
   <slot>
   <div class="text-tips">{{ text }}</div>
   </slot>
  </main>
  <footer class="modal-footer" v-if="showFooter">
   <slot name="footer">
   <button class="modal-btn modal-btn-primary" @click.stop="onConfirm">
    {{ confirmBtnText }}
   </button>
   <button class="modal-btn modal-btn-default" @click.stop="onClose">
    {{ cancelBtnText }}
   </button>
   </slot>
  </footer>
  </section>
 </section>
 </transition>
</template>

添加组件属性及操作方法

添加组件的属性,其中duration属性如果设定的数值小于10,则会乘以1000;否则按传递的数值计算

<script>
 export default {
 name: "EchiModal",
 props: {
  visible: {
  type: Boolean,
  default: false
  },
  title: {
  type: String,
  default: "标题"
  },
  text: {
  type: String,
  default: "提示信息"
  },
  tinyBar: {
  type: Boolean,
  default: false
  },
  confirmBtnText: {
  type: String,
  default: "确定"
  },
  cancelBtnText: {
  type: String,
  default: "返回"
  },
  contentStyle: {
  type: Object,
  default: () => {}
  },
  showClose: {
  type: Boolean,
  default: true
  },
  plain: {
  type: Boolean,
  default: false
  },
  showHeader: {
  type: Boolean,
  default: true
  },
  showFooter: {
  type: Boolean,
  default: true
  },
  showMask: {
  type: Boolean,
  default: true
  },
  onMask: {
  type: Boolean,
  default: false
  },
  duration: {
  type: Number,
  default: 0
  }
 },
 watch: {
  visible(nv) {
  if (nv) {
   this.closeTimerHandle()
  }
  }
 },
 data() {
  return {
  closeTimer: null,
  }
 },
 methods: {
  onClose() {
  this.$emit("on-close");
  this.hide();
  },
  onConfirm() {
  this.$emit("on-confirm");
  },
  hide() {
  this.$emit("update:visible", false);
  this.$emit("on-closed");
  clearTimeout(this.closeTimer);
  this.closeTimer = null;
  },
  clickMask() {
  if (this.onMask && this.showMask) {
   this.hide();
  }
  },
  closeTimerHandle() {
  try {
   if (this.duration <= 0) {
   return;
   }
   const duration = (this.duration < 10) ? (this.duration * 1000) : this.duration;
   clearTimeout(this.closeTimer);
   this.closeTimer = setTimeout(() => {
   this.onClose();
   }, duration);
  } catch (e) {
   console.log(e)
  }
  }
 }
 };
</script>

添加样式声明

<style scoped lang="scss">
 *,
 :after,
 :before {
 box-sizing: border-box;
 outline: none;
 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
 }

 $color-tips: #1ab394;
 $color-text: rgba(255, 255, 255, 0.6);
 $color-info: #ff9900;
 $color-default: #ccc;

 .modal {
 display: block;
 width: 100%;
 height: 100%;
 position: fixed;
 top: 0;
 left: 0;
 z-index: 99;

 .modal-mask {
  display: block;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.5);
 }

 .modal-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
 }

 .modal-content {
  display: flex;
  flex-direction: column;
  min-width: 360px;
  box-shadow: 0 1px 8px 0 rgba(0, 30, 24, 0.05);
  background-color: #fff;
  border-radius: 6px;
  overflow: hidden;
 }

 .modal-header {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 44px;
  font-size: 18px;
  padding: 0 20px;
  font-weight: 500;
  color: #fff;
  background-color: $color-tips;
  z-index: 9999;

  .closed {
  position: absolute;
  top: 50%;
  right: 0;
  font-size: 12px;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  color: #fff;
  transform: translateY(-50%);
  }

  &.modal-plain {
  background-color: rgba(245,
   245,
   245,
   1);
  color: $color-tips;

  .closed {
   color: $color-info;
  }
  }
 }

 .modal-body {
  display: block;
  flex: 1;
  background-color: #fff;
  overflow: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
 }

 .modal-footer {
  display: block;
  width: 100%;
  padding: 20px 30px;
  text-align: center;
  background-color: #fff;

  .modal-btn {
  width: 80px;

  +.modal-btn {
   margin-left: 8px;
  }
  }
 }
 }

 .text-tips {
 display: block;
 width: 100%;
 font-size: 16px;
 text-align: center;
 color: #333;
 padding: 40px 60px;
 }

 .modal-btn {
 display: inline-flex;
 padding: 0 12;
 margin: 0;
 align-items: center;
 justify-content: center;
 font-size: 14px;
 font-weight: 400;
 height: 32px;
 text-align: center;
 white-space: nowrap;
 touch-action: manipulation;
 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
 cursor: pointer;
 user-select: none;
 background-image: none;
 text-decoration: none;
 border: 1px solid transparent;
 border-radius: 4px;
 transition: all .3s ease;

 &:link,
 &:visited,
 &:hover,
 &:active {
  text-decoration: none;
 }
 }

 .modal-btn-default {
 background-color: $color-default;
 color: #fff;

 &:link {
  color: #fff;
  background-color: $color-default;
 }

 &:visited {
  color: #fff;
  background-color: $color-default;
 }

 &:hover {
  color: #fff;
  background-color: rgba(170, 170, 170, .85);
 }

 &:active {
  color: #fff;
  background-color: $color-default;
 }

 &[plain] {
  background-color: #fff;
  color: $color-default;
  border: 1px solid $color-default;
 }
 }

 .modal-btn-primary {
 background-color: $color-tips;
 color: #fff;

 &:link {
  color: #fff;
  background-color: $color-tips;
 }

 &:visited {
  color: #fff;
  background-color: $color-tips;
 }

 &:hover {
  color: #fff;
  background-color: rgba(26, 179, 148, 0.85);
 }

 &:active {
  color: #fff;
  background-color: $color-tips;
 }

 &[plain] {
  background-color: #fff;
  color: $color-tips;
  border: 1px solid $color-tips;
 }
 }

 .toggle-enter,
 .toggle-leave-active {
 opacity: 0;
 transform: translatey(-10px);
 }

 .toggle-enter-active,
 .toggle-leave-active {
 transition: all ease .2s;
 }
</style>

使用

<template>
 <div id="app">
 <img alt="Vue logo" src="./assets/logo.png" />
 <div>
  <button @click.stop="showModel_0 = true">
  显示默认样式
  </button>
  <button @click.stop="showModel_1 = true">
  显示素样式
  </button>
  <button @click.stop="showModel_2 = true">
  修改提示语
  </button>
  <button @click.stop="showModel_3 = true">
  自定义内容
  </button>
  <button @click.stop="showModel_4 = true">
  去除Footer
  </button>
  <button @click.stop="showModel_5 = true">
  去除Header
  </button>
  <button @click.stop="showModel_6 = true">
  设置3秒后自动关闭
  </button>
 </div>
 <EchiModal :visible.sync="showModel_0" title="显示默认样式"></EchiModal>
 <EchiModal :visible.sync="showModel_1" title="显示素样式" plain></EchiModal>
 <EchiModal :visible.sync="showModel_2" title="修改提示语" text="哈哈哈哈哈,我把提示信息修改了"></EchiModal>
 <EchiModal :visible.sync="showModel_3" title="自定义内容" :contentStyle="{width: '600px'}">
  <img alt="Vue logo" src="./assets/logo.png" />
 </EchiModal>
 <EchiModal :visible.sync="showModel_4" title="去除Footer" :showFooter="false"></EchiModal>
 <EchiModal :visible.sync="showModel_5" title="去除Header" :showHeader="false"></EchiModal>
 <EchiModal :visible.sync="showModel_6" title="设置3秒后自动关闭" :duration="3"></EchiModal>
 </div>
</template>

<script>
 import EchiModal from "./components/EchiModal.vue";

 export default {
 name: "app",
 components: {
  EchiModal
 },
 data() {
  return {
  showModel_0: false,
  showModel_1: false,
  showModel_2: false,
  showModel_3: false,
  showModel_4: false,
  showModel_5: false,
  showModel_6: false,
  }
 }
 };
</script>

感谢那您的观看,以上就是我为大家带来的模态框组件,本文同步更新于我的github点击前往。

Javascript 相关文章推荐
javascript引导程序
Oct 26 Javascript
取选中的radio的值
Jan 11 Javascript
JQuery each打印JS对象的方法
Nov 13 Javascript
javascript特殊用法示例介绍
Nov 29 Javascript
escape编码与unescape解码汉字出现乱码的解决方法
Jul 02 Javascript
jQuery中insertBefore()方法用法实例
Jan 08 Javascript
jquery单击事件和双击事件冲突解决方案
Mar 02 Javascript
学习Node.js模块机制
Oct 17 Javascript
AngularJs实现聊天列表实时刷新功能
Jun 15 Javascript
Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)
Aug 24 Javascript
微信小程序动态添加view组件的实例代码
May 23 Javascript
vue中template的三种写法示例
Oct 21 Javascript
详解vue的数据劫持以及操作数组的坑
Apr 18 #Javascript
微信小程序 setData 对 data数据影响问题
Apr 18 #Javascript
详解JavaScript中关于this指向的4种情况
Apr 18 #Javascript
vue.js高德地图实现热点图代码实例
Apr 18 #Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
Apr 18 #Javascript
Vue的H5页面唤起支付宝支付功能
Apr 18 #Javascript
详解Vue中的scoped及穿透方法
Apr 18 #Javascript
You might like
国外比较好的几个的Php开源建站平台小结
2010/04/22 PHP
浅析PKI加密解密 OpenSSL
2013/07/01 PHP
php使用for语句输出三角形的方法
2015/06/09 PHP
php实现简单加入购物车功能
2017/03/07 PHP
关于PHP定时发送服务的解决办法
2017/04/23 PHP
利用PHPExcel读取Excel的数据和导出数据到Excel
2017/05/12 PHP
yii2 上传图片的示例代码
2018/11/02 PHP
imagettftext() 失效,不起作用
2021/03/09 PHP
JavaScript 异步调用框架 (Part 2 - 用例设计)
2009/08/03 Javascript
jquery 常用操作方法
2010/01/28 Javascript
基于jQuery的消息提示插件之旅 DivAlert(三)
2010/04/01 Javascript
js完美的div拖拽实例代码
2014/01/22 Javascript
JavaScript中Function()函数的使用教程
2015/06/04 Javascript
jQuery实现网页抖动的菜单抖动效果
2015/08/07 Javascript
XML文件转化成NSData对象的方法
2015/08/12 Javascript
全系IE支持Bootstrap的解决方法
2015/10/19 Javascript
JavaScript判断用户名和密码不能为空的实现代码
2016/05/16 Javascript
jquery.validate使用详解
2016/06/02 Javascript
扩展jquery easyui tree的搜索树节点方法(推荐)
2016/10/28 Javascript
Bootstrap popover用法详解
2016/12/22 Javascript
微信小程序 网络请求(post请求,get请求)
2017/01/17 Javascript
基于jQuery ztree实现表格风格的树状结构
2018/08/31 jQuery
微信小程序事件对象中e.target和e.currentTarget的区别详解
2019/05/08 Javascript
p5.js实现简单货车运动动画
2019/10/23 Javascript
微信小程序实现图片压缩
2019/12/03 Javascript
vue3.0+vue-router+element-plus初实践
2020/12/02 Vue.js
以windows service方式运行Python程序的方法
2015/06/03 Python
详解python中字典的循环遍历的两种方式
2017/02/07 Python
Django基础之Model操作步骤(介绍)
2017/05/27 Python
详解Python3中ceil()函数用法
2019/02/19 Python
基于Django统计博客文章阅读量
2019/10/29 Python
Python Pillow.Image 图像保存和参数选择方式
2020/01/09 Python
AutoShack.com加拿大:北美主要的汽车零部件零售商
2019/07/24 全球购物
公司年会抽奖活动主持词
2014/03/31 职场文书
乡镇食品安全责任书
2014/07/28 职场文书
七年级之开学家长寄语35句
2019/09/05 职场文书