让你的el-dialog更优雅__Vue.js
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利
在使用Vue + Element 实现需求时常会遇到单个Vue文件内出现多个弹窗需求,一般会这样写
<!--*.vue-->
<template>
<el-dialog :visible="visible1">弹框1</el-dialog>
<el-dialog :visible="visible2">弹框2</el-dialog>
</template>
<script>
export default {
return {
visible1: false,
visible2: false
}
}
</script>
这样的写法在文件内容多的时候容易出现模板臃肿的问题,而且需要外部管理弹窗组件的开关状态visible
可以如何改进
可以考虑将el-dialog封装成Service来使用
<!--*.vue-->
<script>
// 笔者习惯将src设置alias为@
import DialogService from '@/service/dialog'
showDialog() {
DialogService({ /* 弹框内需要用的data */})
}
</script>
如何实现
- 首先需要定义DialogService的入口,内部通过
Vue.extend
I对组件模板进行继承
// src/service/dialog/index.js
import Vue from 'vue'
import dialogTemplate from './dialogTemplate.vue'
const DialogConstructor = Vue.extend(dialogTemplate)
import { isPlainObject } from 'lodash'
export default options => {
let instance
return function() {
// 单例模式,惰性返回弹窗实例
if (instance) {
instance.visible = true
return instance
}
instance = new DialogConstructor({
data: isPlainObject(options) ? { ...options } : {}
})
instance.$mount()
document.body.appendChild(instance.$el)
instance.visible = true
// 暴露实例方便后续的Ref操作
return instance
}
}
- 接下来是dialogTemplate的实现,可根据实际业务进行调整,以下代码仅作为参考
<!--src/service/dialog/dialogTemplate.vue-->
<template>
<el-dialog :title="title" :visible.sync="visible">
<el-table :height="300" :data="tblData">
<el-table-column
props="prop1"
label="col1"
align="center"
></el-table-column>
<el-table-column
props="prop2"
label="col2"
align="center"
></el-table-column>
<el-table-column
Props="prop3"
label="col3"
align="center"
></el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button v-show="submitVisible" size="small" @click="handleCancel">
{{ cancelText }}
</el-button>
<el-button
v-show="cancelVisible"
size="small"
type="primary"
@click="handleSubmit"
>
{{ submitText }}
</el-button>
</div>
</el-dialog>
</template>
<script>
import { isFunction } from 'lodash'
export default {
data() {
return {
visible: false,
title: '',
labelWidth: '100px',
content: null,
tblData: [],
/* footer */
submitVisible: true,
submitText: '确定',
onSubmit: null,
cancelVisible: true,
cancelText: '取消',
onCancel: null
}
},
methods: {
handleSubmit() {
if (isFunction(this.onSubmit)) {
this.onSubmit({ done: this._done })
}
},
handleCancel() {
if (isFunction(this.onCancel)) {
this.onCancel({
done: this._done
})
}
},
_done() {
this.visible = false
},
_destory() {
this.$destroy()
}
}
}
</script>
业务代码中使用
- 渲染一个带表格的弹窗
<!--*.vue-->
<template>
<el-button @click="showDialog">召唤表格</el-button>
</template>
<script>
import DialogService from '@/service/dialog'
export default {
data() {
return {
dialogInstance: null
}
}
methods: {
showDialog() {
this.dialogInstance = dialogService({
title: '带表格的Dialog',
onCancel: ({ done }) => done()
})
}
}
}
</script>
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 夜露死苦 原文链接:https://juejin.im/post/6844904067001483271