基于vue的modal实现(仿monday.com的modal)
写modal要有一个父组件,一个子组件。父组件中点击打开modal,子组件中关闭nodal. 这里通过v-if来实现modal的打开和关闭。
父组件 mondayModal.vue
<template>
<div class="mondayModal">
<h4>{{txt}}</h4>
<h3 @click='isShow = true'>点击打开dialog</h3>
<mondayDialog v-if='isShow' :show='isShow' @change='changeShow'/>
</div>
</template>
<script>
import mondayDialog from './mondayDialog.vue'
export default {
name: "mondayModal",
data: () => ({
txt: '仿monday的modal',
isShow: false
}),
components: {
mondayDialog
},
methods: {
changeShow(val) {
this.isShow = val
}
}
}
</script>
<style lang='scss' scoped>
//清除默认样式的css
@import '../style/reset.css';
.mondayLmitation{
width: 100%;
height: 100%;
h4{
text-align: center;
}
h3{
cursor: pointer;
}
}
</style>
子组件mondayDialog.vue
<template>
<transition name='slide-fade'>
<div class="mondayDialog">
<div class="modal-background"></div>
<div class="content">
<div class="close-dialog">
<a @click='closeDia'>+</a>
</div>
<h3>{{txt}}</h3>
<p>2014年加入monday.com</p>
<p>有大概30000多人加入monday.com</p>
<div class="buttonBox">
<input type="text" name="" value="" placeholder='Enter your work email'>
<div class="sendButton">
<button type="button" name="button">Create Free Account</button>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: "mondayDialog",
data: () => ({
a: 1,
txt: 'I want to hug the people that created this.',
opendialog: true
}),
props: ['show'],
methods: {
closeDia () {
this.show = this.opendialog
this.opendialog = false
this.$emit('change',this.opendialog)
}
}
}
</script>
<style lang="scss" scoped>
@import '../style/reset.css';
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to {
opacity: 0;
}
.mondayDialog{
.modal-background{
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: #333;
opacity: 0.9;
z-index: 999;
transition: all 2s ease-out;
}
.close-dialog{
width: 60px;
height: 60px;
background: linear-gradient(45deg, rgb(120,120,120) 0%, rgb(120, 120, 120) 50%, rgb(52, 52, 52) 50%, rgb(34, 34, 34) 61%);
border-radius: 0 0 0 5px;
position: absolute;
top: 0;
right: 0;
a{
color: rgb(120, 120,120);
font-size: 40px;
// font-weight: 400;
position: absolute;
right: 5px;
top: -10px;
transform: rotateZ(45deg);
cursor: pointer;
}
}
.content{
width: 720px;
position: fixed;
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%,0);
padding: 60px 40px 40px;
text-align: center;
background: rgb(51, 51, 51);
z-index: 1000;
color: rgb(255, 255, 255);
h3{
font-size: 3vw;
font-weight: 500;
text-align: center;
padding: 0;
margin: 0;
}
p{
padding: 5px;
}
.buttonBox{
padding: 20px;
width: 100%;
height: 90px;
input{
width: 60%;
float: left;
height: 100%;
border: none;
text-align: center;
border-radius: 30px 0 0 30px;
color: #333;
outline: none;
}
.sendButton{
float: left;
width: 40%;
height: 100%;
button{
border: none;
height: 100%;
width: 100%;
color: #333;
background: orange;
border-radius: 0 30px 30px 0;
outline: none;
}
button:hover{
opacity: 0.7;
}
}
}
}
}
</style>
实现效果:
要点1 :(css样式)
modal的背景div和内容的div都要固定定位。
modal的背景:z-index: 999;
.modal-background{
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: #333;
opacity: 0.9;
z-index: 999;
transition: all 2s ease-out;
}
modal的内容:z-index: 1000;
.content{
width: 720px;
position: fixed;
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%,0);
padding: 60px 40px 40px;
text-align: center;
background: rgb(51, 51, 51);
z-index: 1000;
color: rgb(255, 255, 255)
}
右上角的折角效果:
.close-dialog{
width: 60px;
height: 60px;
background: linear-gradient(45deg, rgb(120,120,120) 0%, rgb(120120, 120) 50%, rgb(52, 52, 52) 50%, rgb(34, 34, 34) 61%);
border-radius: 0 0 0 5px;
position: absolute;
top: 0;
right: 0;
}
重要的是:background: linear-gradient(45deg, rgb(120,120,120) 0%, rgb(120120, 120) 50%, rgb(52, 52, 52) 50%, rgb(34, 34, 34) 61%);
button移上的时候,颜色变暗:
button{
opacity: 0.7;
}
要点2 :通过vue的父子组件的通信,控制modal的打开关闭
父组件中
<mondayDialog v-if='isShow' :show='isShow' @change='changeShow'/>
model通过 isShow 的值来确定是否显示,在父组件中点击来打开model.
<h3 @click='isShow = true'>点击打开dialog</h3>
父组件又将isShow的值传递给子组件,子组件中定义一个closeDia
的方法,通过this.$emit('change',val),将更改后的值传递给父组件,使model关闭。
<a @click='closeDia'>+</a>
props: ['show'],
methods: {
closeDia () {
this.show = this.opendialog
this.opendialog = false
this.$emit('change',this.opendialog)
}
}
在子组件中不能直接更改父组件传递过来的show的值,所以先将show的值赋值给b,更改b的值,将b传递给父组件,在父组件中,再将b的值赋值给show,来关闭model。