欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue组件系列开发之模态框

程序员文章站 2023-12-05 20:40:28
项目基础工程文件是使用vue-cli3.0搭建的,这里不过多介绍。开发vue组件系列之模态框,主要有标题、内容、定时器、按钮文案、按钮事件回调、遮罩层这些可配置项。本次开发...

项目基础工程文件是使用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点击前往。