实现思路(核心):
- 封装时可借助ekement-ui(样式)
- 利用好 $listener, $attr隔代传值,在组件中调用属性或方法
- slot插槽的运用
$listener, $attr的详细用法:
https://blog.youkuaiyun.com/lqlq54321/article/details/106389054
*首次封装
<template>
<div v-if="show">
<div :class="{'base-dialog--mask': true, 'base-dialog--mask--white': styleType === 'white'}">
<div class="base-dialog--content" :style="width&&{width:width}">
<div class="base-dialog--header" :style="titleHeight&&{height:titleHeight, lineHeight: titleHeight}">
<slot name="header">
{{title}}
<br ref="defaultFocus" tabindex="0" />
<div class="base-dialog--header-close" @click="cancel" :style="iconSize&&{height:iconSize, width: iconSize}"></div>
</slot>
</div>
<div class="base-dialog--main">
<slot></slot>
</div>
<div v-if="!nofooter" class="base-dialog--footer">
<slot name="footer">
<template v-if="isConfirmDialog">
<BaseButton class="del" @click="btnClick">{{submitBtnText}}</BaseButton>
<BaseButton type="plain" class="cancel" @click="cancel">取消</BaseButton>
</template>
<template v-else>
<BaseButton class="know" @click="closeDialog">我知道了</BaseButton>
</template>
</slot>
</div>
</div>
</div>
</div>
</template>
export default {
inheritAttrs: false,
components: {
BaseButton,
},
props: {
show: {
type: Boolean,
default: false,
},
title: String,
width: String,
submitBtnText: {
type: String,
default: "确定",
},
failBtnText: {
type: String,
default: "取消",
},
dialogType: {
type: String,
default: "confrim",
},
nofooter: {
type: Boolean,
default: false,
},
},
computed: {
isConfirmDialog() {
return this.dialogType === "confrim";
},
},
watch: {
show: {
handler(val) {
if (val) {
this.$emit("open");
this.$nextTick(() => {
if (!this.isConfirmDialog) {
this.focus();
} else {
this.$refs.defaultFocus.focus();
}
});
}
},
immediate: true,
},
},
mounted() {
const body = document.body;
if (body.append) {
body.append(this.$el);
} else {
body.appendChild(this.$el);
}
},
destroyed() {
this.$el.remove();
},
methods: {
btnClick() {
this.$emit("btnClick");
this.closeDialog();
},
cancel() {
this.$emit("cancel");
this.closeDialog();
},
closeDialog() {
this.$emit("close");
this.$emit("update:show", false);
},
focus() {
this.$nextTick(() => {
deepRun(this.$refs.firstButton, "focus");
});
},
},
};
注释:BaseButton为一个组件
二次封装
<template>
<BaseDialog class="normal-dialog" ref="baseDialog" :show="show" v-bind="$attrs" v-on="$listeners">
<div class="normalDiaglogContent">
<slot></slot>
</div>
</BaseDialog>
</template>
import BaseDialog from "./BaseDialog.vue";
export default {
components: { BaseDialog },
inheritAttrs: false,
props: { show: Boolean },
watch: {
show(val) {
if (val) {
this.$nextTick(() => {
this.focus();
});
}
}
},
methods: {
focus() {
this.$refs.baseDialog.focus();
}
}
};