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 相关文章推荐
Jquery 表单取值赋值的一些基本操作
Oct 11 Javascript
javascript中通过arguments参数伪装方法重载
Oct 08 Javascript
js实现鼠标点击左上角滑动菜单效果代码
Sep 06 Javascript
在JavaScript中call()与apply()区别
Jan 22 Javascript
浅谈jQuery 选择器和dom操作
Jun 07 Javascript
ionic组件ion-tabs选项卡切换效果实例
Aug 27 Javascript
jQuery实现链接的title快速出现的方法
Feb 20 Javascript
使用InstantClick.js让页面提前加载200ms
Sep 12 Javascript
微信小程序的线程架构【推荐】
May 14 Javascript
javaScript把其它类型转换为Number类型
Oct 13 Javascript
微信小程序按顺序同步执行的两种方式
Dec 20 Javascript
vue实现图书管理系统
Dec 29 Vue.js
详解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判断是否为json格式的方法
2014/03/04 PHP
php生成固定长度纯数字编码的方法
2015/07/09 PHP
PHP针对字符串开头和结尾的判断方法
2016/07/11 PHP
thinkphp5 框架结合plupload实现图片批量上传功能示例
2020/04/04 PHP
jQuery获取当前对象标签名称的方法
2014/02/07 Javascript
jquery实现点击消失的代码
2014/03/03 Javascript
浅谈javascript 迭代方法
2015/01/21 Javascript
JS实现鼠标箭头变成一个燃烧烛光效果的方法
2015/02/28 Javascript
jQuery EasyUI中的日期控件DateBox修改方法
2016/11/09 Javascript
JS实现区分中英文并统计字符个数的方法示例
2018/06/09 Javascript
nuxt框架中对vuex进行模块化设置的实现方法
2019/09/06 Javascript
vue项目中常见问题及解决方案(推荐)
2019/10/21 Javascript
微信小程序获取当前位置和城市名
2019/11/13 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
Python编程实现使用线性回归预测数据
2017/12/07 Python
对DJango视图(views)和模版(templates)的使用详解
2019/07/17 Python
使用python telnetlib批量备份交换机配置的方法
2019/07/25 Python
Python操作excel的方法总结(xlrd、xlwt、openpyxl)
2019/09/02 Python
python GUI库图形界面开发之PyQt5动态(可拖动控件大小)布局控件QSplitter详细使用方法与实例
2020/03/06 Python
详解python环境安装selenium和手动下载安装selenium的方法
2020/03/17 Python
Jupyter 无法下载文件夹如何实现曲线救国
2020/04/22 Python
django美化后台django-suit的安装配置操作
2020/07/12 Python
python3中calendar返回某一时间点实例讲解
2020/11/18 Python
HTML5中Localstorage的使用教程
2015/07/09 HTML / CSS
联想西班牙官网:Lenovo西班牙
2018/08/28 全球购物
全球精选男装和家居用品:Article
2020/04/13 全球购物
求职简历推荐信范文
2013/12/02 职场文书
期终自我鉴定
2014/02/17 职场文书
启动仪式策划方案
2014/06/14 职场文书
公司委托书格式范本
2014/09/16 职场文书
专题组织生活会发言材料
2014/10/17 职场文书
2014年公路养护工作总结
2014/12/04 职场文书
表扬信范文
2019/04/22 职场文书
Nginx搭建rtmp直播服务器实现代码
2021/03/31 Servers
Python中glob库实现文件名的匹配
2021/06/18 Python
Kubernetes关键组件与结构组成介绍
2022/03/31 Servers