shu-c-view
Version:
rollup 打包vue@2.7组件库框架
208 lines (206 loc) • 6.19 kB
JavaScript
/**
* @desc 对话框
*/
import _assign from 'lodash/assign';
import _omit from 'lodash/omit';
import _keys from 'lodash/keys';
import _has from 'lodash/has';
import _get from 'lodash/get';
import _concat from 'lodash/concat';
import { h } from 'vue';
// import { useRoute, useRouter } from 'vue-router/composables';
/**
* @typedef {Object} options - 选项配置对象
* @property {Object} component - 组件对象
* @property {Object} container - html 节点容器
*/
/**
* @param {options} options - 选项配置
* @example
* mounted(){
* this.dialogInstance = this.$baseDialog({component: Detail,container: this.$el,title: '添加',slotNode: {}});
* },
* methods: {
* onOpenBaseDialog() {
* this.dialogInstance.open();
* }
* }
*/
const BaseDialog = function(Vue) {
return function(options = {}) {
// const that = this;
let contentNode = null;
const optionsKey = _keys(_omit(options, ['$route', '$router']));
/* const $route = useRoute();
const $router = useRouter(); 如果在具体某个方法中创建的弹框对象这里获取router对象会报错 */
const VueModal = Vue.extend({
provide() {
return {
getBaseDialog: this
};
},
// router: that.$router, vue@2.7版本弃用
// store: that.$store, vue@2.7版本弃用-2.7版本弃用vuex改用pinia
router: options.$router, // vue2.7版本,传递到弹框的详情组件中使用:const { $route, $router } = getCurrentInstance().proxy;
route: options.$route,
props: optionsKey,
render(h) {
let customClass = 'base-el-dialog';
if (
_has(this.$props, 'customClass') ||
_has(this.$props, 'custom-class')
) {
customClass += ` ${_get(this.$props, 'customClass', '')} ${_get(
this.$props,
'custom-class',
''
)}`;
}
contentNode = h();
if (_has(options.component, 'render')) {
contentNode = h(options.component);
} else if (_has(options.component(), 'el')) {
const detailOption = options.component();
contentNode = h(detailOption.el, _omit(detailOption, ['el']), [
_get(detailOption, 'children')
]); // ref 对象无法获取
} else {
contentNode = options.component();
}
return h(
'el-dialog',
{
class: {
'base-dialog__wrapper': true,
[options.ctCls]: options.ctCls
},
props: _assign(
{
// destroyOnClose: true,
title: '详情',
visible: this.visible,
customClass
},
_omit(this.$props, ['listeners', 'customClass']),
{}
),
on: {
open: () => {
if (_has(options, 'listeners.open')) {
options.listeners.open();
}
},
opened: () => {
if (_has(options, 'listeners.opened')) {
options.listeners.opened();
}
},
close: () => {
this.visible = false;
if (_has(options, 'listeners.close')) {
options.listeners.close();
}
},
closed: () => {
if (options.isDestroy) {
this.$destroy();
if (_has(this, '$el')) {
this.$el.remove();
}
} else if (_has(options, 'listeners.closed')) {
options.listeners.closed();
}
}
}
},
[
contentNode,
h('template', { slot: 'title' }, this.appendTitle()),
h('template', { slot: 'footer' }, this.appendFooter())
]
);
}
});
const instance = new VueModal({
propsData: options,
data() {
return {
visible: false
};
},
created() {
this.$nextTick(() => {
document.body.appendChild(instance.$mount().$el);
});
},
methods: {
// 详情组件引用
getContentNode() {
return contentNode.componentInstance;
},
// 打开
open() {
setTimeout(() => {
this.visible = true;
}, 0);
},
// 关闭
close() {
setTimeout(() => {
this.visible = false;
}, 0);
},
// 关闭(销毁实例)
closeDialog() {
if (_has(options, 'listeners.close')) {
options.listeners.close();
}
setTimeout(() => {
instance.$destroy();
if (_has(instance, '$el')) {
instance.$el.remove();
}
}, 0);
},
// Dialog 标题区的内容
appendTitle() {
return _has(this.$props, 'slotNode.title')
? [this.$props.slotNode.title(h)]
: [];
},
// Dialog 按钮操作区的内容
appendFooter() {
const buttonsVNode = [];
for (
let i = 0, len = _get(options, 'buttons', []).length;
i < len;
i += 1
) {
const option = options.buttons[i];
buttonsVNode.push(
h(
'el-button',
{
props: _get(option, 'props', function() {
return {};
})(),
on: option.on
},
[option.text]
)
);
}
return _has(this.$props, 'slotNode.footer')
? _concat([this.$props.slotNode.footer(h)], buttonsVNode)
: _concat([], buttonsVNode);
}
}
});
/* if (_has(options, 'container')) {
options.container.appendChild(instance.$mount().$el);
} */
// document.body.appendChild(instance.$mount().$el);
return instance;
};
};
export { BaseDialog };