项目基础工程文件是使用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"os").cpus().length > 1,
devServer: {
port: 9595, // 端口号
open: true, // 自动开启浏览器
compress: true, // 开启压缩
overlay: {
warnings: true,
errors: true
}
}
};
项目结构
├── src # 项目源码。开发的时候代码写在这里。 │ ├── components # 组件目录 | | |--EchiModal # 模态框组件 │ ├── App.vue # 项目根视图 │ ├── main.js # 程序主入口
部分截图
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) "htmlcode">
<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="/UploadFiles/2021-04-02/logo.png">
感谢那您的观看,以上就是我为大家带来的模态框组件,本文同步更新于我的github点击前往。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
暂无“Vue组件系列开发之模态框”评论...
更新动态
2025年11月05日
2025年11月05日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]


