При использовании 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
как это можно улучшить
заимствованныйИспользование службы модального компонента NgZoro
Рассмотрите возможность инкапсуляции el-dialog в качестве службы для использования
<!--*.vue-->
<script>
// 笔者习惯将src设置alias为@
import DialogService from '@/service/dialog'
showDialog() {
DialogService({ /* 弹框内需要用的data */})
}
</script>
Как добиться
- Во-первых, вам нужно определить запись DialogService, которая передается внутри
Vue.extendЯ наследую шаблон компонента
// 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>