赞
踩
一个基于Vue.js和Element UI框架的自定义对话框组件。这个组件名为biuDialog
,封装了Element UI的el-dialog
组件,并添加了一些自定义的功能和样式。
自定义标题和底部:组件允许通过插槽(slots)来自定义对话框的标题和底部内容。如果没有提供自定义内容,它会使用默认的标题和底部按钮(取消和确定)。
控制显示和隐藏:通过visible
属性来控制对话框的显示和隐藏。show
计算属性与visible
属性同步,当show
改变时,会通过$emit
通知父组件。
事件回调:提供了open
、opened
、close
和closed
事件,以便在对话框打开或关闭时执行特定的逻辑。
关闭逻辑:beforeClose
方法允许在关闭对话框之前执行一些逻辑,例如确认操作。beforeClose2
方法是一个快捷方式,它在用户点击关闭按钮时触发。
样式定制:通过customClass
属性可以添加自定义样式。默认情况下,对话框有一个基础样式,可以通过SCSS样式部分进行修改。
visible
: 对话框是否可见。title
: 对话框标题。appendToBody
: 对话框是否插入到body元素上。modal
: 是否需要遮罩层。fullscreen
: 是否全屏。destroyOnClose
: 关闭时是否销毁对话框中的元素。width
: 对话框宽度。top
: 对话框距离顶部的距离。customClass
: 自定义类名。showClose
: 是否显示关闭按钮。closeOnClickModal
: 是否可以通过点击遮罩层关闭对话框。beforeClose
: 关闭前的回调函数。open
: 触发open
事件。opened
: 触发opened
事件。close
: 触发close
事件。closed
: 触发closed
事件。cancel
: 触发cancel
事件,通常用于取消操作。submit
: 触发submit
事件,通常用于确认操作。样式使用了SCSS,并且是作用域化的,这意味着样式只应用于当前组件。对话框的头部和底部有特定的样式,可以通过修改这些样式来改变对话框的外观。
这个组件可以很容易地集成到使用Element UI的Vue.js项目中,为开发者提供了一个灵活且易于定制的对话框解决方案。
<template> <div class="biu-dialog-box"> <el-dialog :custom-class="customClass" :title="$slots.title ? '' : title" :visible.sync="show" :width="width" :top="top" :append-to-body="appendToBody" :modal="modal" :fullscreen="fullscreen" :destroy-on-close="destroyOnClose" :modal-append-to-body="modalAppendToBody" :before-close="beforeClose" :close-on-click-modal="closeOnClickModal" :show-close="false" @open="open" @opened="opened" @close="close" @closed="closed" > <!-- 有写弹窗头部则采用输入的 --> <template v-if="$slots.title"> <span slot="title"> <slot name="title" /> </span> </template> <!-- 自定义默认头部 --> <template v-if="!$slots.title"> <div slot="title" class="biu-default-header-box"> <div class="biu-default-header-title">{{ title }}</div> <div class="biu-default-header-close" @click="beforeClose2" v-if="showClose" > <span class="biu-icon-guanbi2"> <i class="el-icon-circle-close" style="font-size:16px"></i> </span> </div> </div> </template> <!-- 弹窗内容区域 --> <slot /> <!-- 弹窗底部区域 --> <template v-if="$slots.footer"> <span slot="footer"> <slot name="footer" /> </span> </template> <!-- 自定义默认头部 --> <template v-if="!$slots.footer"> <div slot="footer" class="biu-default-header-box"> <el-button class="btn" @click="cancel">取消</el-button> <el-button class="btn sure" @click="submit">确定</el-button> </div> </template> </el-dialog> </div> </template> <script> export default { name: "biuDialog", props: { visible: { type: Boolean, default: false, }, title: { type: String, default: "提示", }, appendToBody: { // Dialog 自身是否插入至 body 元素上。嵌套的 Dialog 必须指定该属性并赋值为 true type: Boolean, default: true, }, modalAppendToBody: { // 遮罩层是否插入至 body 元素上,若为 false,则遮罩层会插入至 Dialog 的父元素上 type: Boolean, default: true, }, modal: { // 是否需要遮罩层 type: Boolean, default: true, }, fullscreen: { // 是否全屏 type: Boolean, default: false, }, destroyOnClose: { // 关闭时销毁 Dialog 中的元素 type: Boolean, default: true, }, width: { type: String, default: "30%", }, top: { type: String, default: "15vh", }, customClass: { type: String, default: "biu-dialog", }, showClose: { type: Boolean, default: false, }, closeOnClickModal: { type: Boolean, default: true, }, beforeClose: { type: Function, }, }, computed: { show: { get() { return this.visible; }, set(val) { this.$emit("update:visible", val); // visible 改变的时候通知父组件 }, }, }, data() { return {}; }, methods: { //点击自定义的关闭按钮 beforeClose2() { this.beforeClose(() => { this.show = false; }); }, open() { // Dialog 打开的回调 this.$emit("open"); }, opened() { // Dialog 打开动画结束时的回调 this.$emit("opened"); }, close() { // Dialog 关闭的回调 this.$emit("close"); }, closed() { // Dialog 关闭动画结束时的回调 this.$emit("closed"); }, cancel() { this.$emit("cancel"); }, submit() { this.$emit("submit"); }, }, }; </script> <style scoped lang="scss"> :deep(.el-dialog) { min-width: 320px; .el-dialog__header { padding: 0; color: #d37332; font-weight: 500; height: 50px; display: flex; flex-direction: column; justify-content: center; border-bottom: 2px solid #e9e8e8; font-size: 14px; .biu-default-header-box { padding: 0 20px; display: flex; line-height: 20px; .biu-default-header-title { flex: 1; } .biu-default-header-close { width: 15px; height: 15px; cursor: pointer; } } } .el-dialog__footer { padding: 0; text-align: center; height: 88px; border-top: 2px solid #e9e8e8; display: flex; justify-content: center; flex-direction: column; .btn { width: 120px; height: 40px; background: #e9e8e8; border-radius: 2px; } .sure { color: #ffffff; background: #de9a6c; margin-left: 66px; } } } </style>
在使用biuDialog
组件时,您可以通过Vue的插槽(slots)机制来自定义对话框的标题和底部。插槽允许您插入自定义的HTML、组件或者任何其他Vue实例,从而实现高度的灵活性和可定制性。
要自定义对话框的标题,您可以在组件实例中使用<slot>
元素,并给它命名(在这个例子中是title
)。例如:
<template>
<biu-dialog :visible.sync="dialogVisible" title="我的对话框">
<span slot="title">
<h1 class="custom-title">这是自定义标题</h1>
</span>
<!-- 对话框的其他内容 -->
</biu-dialog>
</template>
在这个例子中,<span slot="title">
定义了一个名为title
的插槽,您可以在其中放置任何您想要的内容。biuDialog
组件会检查是否有任何内容被插入到title
插槽中,如果有,它将使用这些内容作为对话框的标题。
自定义对话框底部的方法与自定义标题类似。您需要在biuDialog
组件中使用<slot>
元素,并为其命名为footer
。例如:
<template>
<biu-dialog :visible.sync="dialogVisible" title="我的对话框">
<!-- 对话框的内容 -->
<span slot="footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</span>
</biu-dialog>
</template>
在这个例子中,<span slot="footer">
定义了一个名为footer
的插槽,您可以在其中放置任何您想要的按钮或其他元素。当您需要不同的按钮或逻辑时,只需在插槽内容中进行更改即可。
biuDialog
组件将不会显示其默认的标题和底部。如果希望弹框内容通过配置显示,而不是硬编码在模板中,可以采用以下方法:
props
传递配置您可以在父组件中定义一些数据,这些数据将作为配置传递给biuDialog
组件。然后,在biuDialog
组件内部使用这些配置来动态渲染内容。
<template> <div> <!-- 触发弹框的按钮 --> <el-button @click="openDialog">打开对话框</el-button> <!-- 使用biuDialog组件 --> <biu-dialog :visible.sync="dialogVisible" :config="dialogConfig" > </biu-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false, dialogConfig: { title: '配置标题', content: '这是通过配置显示的内容' // 可以添加更多配置项,如按钮文本、样式等 } }; }, methods: { openDialog() { this.dialogVisible = true; } } }; </script>
biuDialog
组件以接收和使用配置您需要在biuDialog
组件中添加新的props
来接收配置,并在组件的模板中使用这些配置来渲染内容。
biuDialog
组件修改示例export default {
// ...
props: {
// ...
config: {
type: Object,
default: () => ({
title: '默认标题',
content: '默认内容'
})
}
},
// ...
};
然后在模板中使用这些配置:
<template>
<!-- ...其他代码... -->
<div v-if="config.title" class="dialog-content">
{{ config.content }}
</div>
<!-- ...其他代码... -->
</template>
在这个例子中,config
对象包含了title
和content
属性,这些属性被用来动态渲染对话框的标题和内容。如果config
对象中的属性不存在,您可以设置默认值或者不渲染相应的内容。
props
中定义的名称相匹配。biuDialog
组件中,您可能需要根据配置的不同来决定是否渲染某些元素,或者如何渲染它们。通过这种方式,可以使弹框内容更加灵活,根据需要轻松更改配置,而无需修改模板代码。
如果弹框内容是一个对象,且该对象包含多个元素,可以将这个对象作为配置传递给biuDialog
组件。然后在组件内部,根据这个对象的结构动态渲染每个元素。
在父组件中,您可以定义一个对象,该对象包含了弹框需要显示的所有元素和配置。然后,通过props
将这个对象传递给biuDialog
组件。
<template> <div> <!-- 触发弹框的按钮 --> <el-button @click="openDialog">打开对话框</el-button> <!-- 使用biuDialog组件 --> <biu-dialog :visible.sync="dialogVisible" :dialog-content-object="contentObject" > </biu-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false, contentObject: { title: '详细信息', elements: [ { type: 'text', content: '这是一段文本。' }, { type: 'image', src: 'path/to/image.jpg' }, { type: 'button', text: '点击我', onClick: this.handleButtonClick } // 更多元素... ] }, handleButtonClick() { // 处理按钮点击事件 console.log('按钮被点击了!'); } } }, methods: { openDialog() { this.dialogVisible = true; } } }; </script>
biuDialog
组件以接收和使用对象配置在biuDialog
组件中,您需要添加一个新的prop
来接收父组件传递的对象,并在模板中遍历这个对象的elements
数组,根据每个元素的type
来决定如何渲染。
export default {
// ...
props: {
// ...
dialogContentObject: {
type: Object,
default: () => ({
title: '',
elements: []
})
}
},
// ...
};
在模板中使用这个对象:
<template> <el-dialog :visible.sync="show" :custom-class="customClass" :title="config.title || dialogContentObject.title" @open="open" @opened="opened" @close="close" @closed="closed" > <!-- 遍历元素数组并渲染每个元素 --> <div v-for="element in dialogContentObject.elements" :key="element.type"> <template v-if="element.type === 'text'"> <p>{{ element.content }}</p> </template> <template v-if="element.type === 'image'"> <img :src="element.src" alt="Image" /> </template> <template v-if="element.type === 'button'"> <el-button @click="element.onClick">{{ element.text }}</el-button> </template> <!-- 更多类型的条件渲染... --> </div> </el-dialog> </template>
在这个例子中,dialogContentObject
对象包含了一个title
和一个elements
数组。elements
数组中的每个元素都有一个type
属性,用于指示应该渲染哪种类型的元素(如文本、图片、按钮等)。模板中的v-for
指令用于遍历这些元素,并根据type
属性使用v-if
或v-else-if
来决定渲染哪种模板。
v-if
/v-else-if
条件渲染逻辑,以支持更多的元素类型。这种方法使得弹框内容的渲染完全基于配置,提供了极高的灵活性和可扩展性。您可以根据需要轻松添加或修改配置对象中的元素,而无需更改组件的模板代码。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。