preface
Pop-up dialog box is widely used in daily development. Whether it is a Web page, or an App, or a desktop application, you can use the dialog box to achieve a high experience of human-computer interaction. Browsing ElementUi, we can see that in its component library, there are many components about pop-up: Dialog box, pop-up box, text prompt, bubble confirmation box……
As for Ui library development, I created a set of open source Ui library project that is compatible with VUE + LESS based on the components of ElementUi. If you are interested, please come to GIT to step on it
Attachment:
- Git – github.com/Jason9708/C…
- Juejin. im/post/684490…
What this article will bring is to touch an ElementUi dialog box, from zero to one to understand how a qualified component is built
What is a component?
Components can be divided into business components and generic components
- The business component
- Only responsible for the specific business, easy to invoke, components and business coupling
- Cannot migrate, scalability is poor
- Common component
- In the abstract
UI
Component, without specific function implementation - Use requires specific business code
- With high reuse, high scalability
- In the abstract
How to think about implementing a qualified component? Think function → extract business function and basic function → implement basic function and define the interface of business function
Create dialog components
Demand analysis
Filtering according to the functional attributes of the ElementUi dialog, we implement the following requirements:
- The dialog box display is controlled by the parent component and implemented by the child component
- Headers pass values through the parent component, or through
slot
- Specific content and the bottom are passed
slot
User-defined - The mask layer, the body scroll, the upper right button, the theme color, custom classes, and so on are configurable
- Callback before the popover closes, callback after the popover opens, and callback after the popover closes
The final result
The code
File directory
index.vue
: Component fileindex.less
: the stylesheetview01.vue
: Tests the component file
1 – index.vue
Component files
❗ Ps:
$slots.footer
– To determine whether the slots used in the parent component include slots named footerthis.$emit('update:visible', false)
– This usage requires the parent component to cooperate in the bindingvisible
The use ofsync
Modifier that allows a child component to modify the value of its parent componenthandleClose
– This method is passed when the parent component has passed beforeClose and it is functionhide()
This usage implements additional operations on the parent component before closingbeforeClose
The function can take one argument, which is used to actively close the popover
<template>
<div class='cai-dialog-wrapper' ref='dialog-wrapper' v-show='visibleDialog' @click.self='handleWrapperClick'>
<transition name="dialog-fade">
<div ref='dialog'
:class="['cai-dialog',{ 'cai-dialog-dark':dark },customClass]"
:style='dialogSize'
v-if='dialogRender'> <! <div class='cai-dialog-header'> <! -- Dialog title, which can be replaced --> <slot name='title'>
<span class='cai-dialog__title'>{{ title }}</span> </slot> <! Close the dialog button --> <buttontype='button'
class='cai-dialog__headerbtn'
aria-label='Close'
v-if='displayClose'
@click='handleClose'>
<i class='cai-icon-close'></i> </button> </div> <! <div class='cai-dialog-body'> <slot></slot> </div> <! <div class='cai-dialog-footer' v-if='$slots.footer'>
<slot name='footer'></slot>
</div>
</div>
</transition>
</div>
</template>
<script>
export default {
name:'CaiDialog'.data() {return{
visibleDialog:false,
dialogRender:false, dialogSize:{} // props:{visible:{type: Boolean,
default: false
},
title:{
type: String,
default: ' '}, // turns off the callback to the pop-up window (which takes one argument)done()) beforeClose: Function, // if the mask layer is needed modal:{type: Boolean,
default: true}, // Whether to lock body scroll when Dialog appears lockScroll: {type: Boolean,
default: true}, // can you close Dialog closeOnClickModal by clicking modal: {type: Boolean,
default: false}, // Whether to display the upper-right close button displayClose:{type: Boolean,
default: trueHigh}, / / the biggest wide width: String, height: String, / / theme colors - highlighting (default) | dark night: {type:Boolean,
default:false}, // customClass: {type:String,
default:' '
}
},
watch:{
visible(newVal){
if(newVal){
this.visibleDialog = true
this.dialogRender = trueChangeDialogStyle () this. ChangeDialogStyle () this.$emit('open')}else{
this.visibleDialog = false
this.dialogRender = false
document.body.style['overflow'] = 'auto'
this.$emit('close')
}
}
},
methods:{
handleWrapperClick() {if(! this.closeOnClickModal)returnThis.handleclose ()}, // handles the closing dialog, called if beforeClose existshandleClose() {if(typeof this.beforeClose === 'function') {
this.beforeClose(this.hide)
}else{
this.hide()
}
},
hide(){
this.$emit('update:visible'.false); }, // Modify the Dialog style based on the Props valuechangeDialogStyle(){// lockScroll - disables the underlying scrollif(this.lockScroll) document.body.style['overflow'] = 'hidden'
var that = this
this.$nextTick(() => {
var dialogWrapperStyle = that.$refs['dialog-wrapper'].style
var dialogStyle = that.$refs.dialog.style
if(that.width) dialogStyle.width = that.width + 'px'
if(that.height) dialogStyle.height = that.height + 'px'// Implement an unmasked layerif(! that.modal) dialogWrapperStyle.background ='transparent'
})
}
}
}
</script>
<style lang='less' scoped>
@import './index.less';
@import '.. /.. /CaiIcon/component/index.less'; // Icon style sheet can be ignored </style>Copy the code
2 – index.less
The stylesheet
.cai-dialog-wrapper{ position: fixed; top:0; bottom:0; right: 0; left: 0; overflow: auto; Background: rgba (0,0,0,0.6); z-index:1999; // Default style.cai-dialog{position:absolute; border:1px solid rgba(247, 241, 240); border-radius:5px; color:# 303952;
padding:10px;
left:50%;
top:50%;
transform:translate(-50%, -50%);
display:flex;
flex-direction: column;
justify-content: space-between;
background: rgba(247, 241, 240);
min-width:200px;
min-height:100px;
overflow: auto;
.cai-dialog-header{
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom:10px;
font-size:14px;
.cai-dialog__title{
font-weight: 600;
}
.cai-dialog__headerbtn{
background: transparent;
border-color: transparent;
padding:0;
outline:none;
.cai-icon-close{
color:# 303952;
cursor:pointer;
transition: all .1s linear;
&:hover{
color:#ff3f34;} } } } .cai-dialog-body{ flex:1; }} // night mode. Cai-dialog-dark {border-color: border-color:#3d3d3d;
background: #3d3d3d;
color:#fff;
.cai-dialog-header{
.cai-dialog__headerbtn{
.cai-icon-close{
color:#fff;
cursor:pointer;
transition: all .1s linear;
&:hover{
color:#ef5777;}}}}} // Enter/leave animation. Dialog-fade -enter-active,.dialog-fade-leave-active {transition: all.3s linear; } .dialog-fade-enter { opacity: 0; top:48%; }}Copy the code
3 – view01.vue
Test component files
<! -- visible - Control display title - popover title beforeClose - Callback modal before popover closes - Whether mask layer is needed lockScroll - whether body scroll is locked when Dialog appears CloseOnClickModal - whether can be closed by clicking on the modal Dialog displayClose - whether show dark corner close button - theme colors - highlighting (default) | customClass - custom class at night @open-dialog Open callback @close-dialog closed callback slot {footer - bottom unnamed - content} --> <div style='width:310px; padding:20px; border:1px solid #DDDDDD; display:flex; flex-wrap:wrap; '>
<cai-button @click='openDialog1'> Highlight dialog box </cai-button> <cai-dialog :visible.sync='showDialog1' closeOnClickModal width='400' height='200' title='I am Light' :before-close='handleDialogClose' @open='DialogOpen' @close='DialogClose'>
I am a Dialog
<span slot="footer" style='display:flex; justify-content:flex-end; '>
<cai-button @click="showDialog1 = false"> </cai-button> < cai-button@click ="showDialog1 = false"> determine < / CAI - button > < / span > < / CAI - dialog > < CAI - divider > < / CAI - divider > < CAI - button @ click ='openDialog2'> Night dialog </cai-button> <cai-dialog :visible.sync='showDialog2' dark :displayClose='false' :lockScroll='false' :before-close='handleDialogClose'> <! -- custom header from slot --> <span slot="title">
I am Dark
</span>
I am a Dialog
<span slot="footer" style='display:flex; justify-content:flex-end; '>
<cai-button @click="showDialog2 = false"> </cai-button> < cai-button@click ="showDialog2 = false"> < span style = "box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; white-space: inherit! Important;"Copy the code
data() {return{
// Dialog
showDialog1:false,
showDialog2:false}}methods() {openDialog1(){
this.showDialog1 = true
},
openDialog2(){
this.showDialog2 = true
},
DialogOpen(){
console.log('DialogOpen')},DialogClose(){
console.log('DialogOpen')
},
handleDialogClose(done){
console.log('Popover is closed')
done()}}Copy the code
The end of the
Component Open Source Address
Github.com/Jason9708/C…
Git is an open source UI library project, currently developed nearly 20 UI components adapted to Vue, interested partners to ⭐
Screenshot of some components