layui/package/layer/src/index.ts
2022-04-20 09:48:35 +08:00

216 lines
5.8 KiB
TypeScript

import { render, h, isVNode, getCurrentInstance, AppContext, App } from "vue";
import LayLayer from "./component/index.vue";
import { InstallOptions } from "./types";
import { zIndexKey } from "./tokens";
import { nextId } from "./utils";
// 实例队列
const layerInstance: any = [];
// 新增实例
const addInstance = (instance: any) => {
layerInstance.push(instance);
};
// 删除实例
const delInstance = (id: any) => {
layerInstance.forEach((item: any, index: number) => {
if (item.modalContainer.id === id) {
// 删除元素
layerInstance.splice(index, 1);
}
});
};
// 清空实例
const cleanInstance = () => {
layerInstance.splice(0, layerInstance.length);
};
// 是否存在
const isExist = (id: any) => {
let b = false;
layerInstance.forEach((item: any, index: number) => {
if (item.modalContainer.id === id) {
b = true;
}
});
return b;
};
// 聚合 modal 配置
const mergeOption = (option: any, defaultOption: any) => {
if (option) defaultOption = Object.assign(defaultOption, option);
return defaultOption;
};
// 创建 modal 容器
const createContainer = () => {
const modalContainer = document.createElement("div");
modalContainer.id = nextId();
document.body.appendChild(modalContainer);
return modalContainer;
};
// modal 子 VNode
const modalChildrenVNode = (content: any) => {
if (typeof content === "function") {
return isVNode(content()) ? { default: () => content() } : undefined;
}
return isVNode(content) ? { default: () => content } : undefined;
};
const layer = {
// 上下文
_context: <AppContext | null>null,
// 页面
open: (option: any, callback: Function) => {
let defaultOption = {};
return layer.create(option, defaultOption, callback);
},
// 抽屉
drawer: (option: any, callback: Function) => {
let defaultOption = {
type: "drawer",
};
return layer.create(option, defaultOption, callback);
},
// 消息
msg: (message: string, option?: any, callback?: Function) => {
let defaultOption = {
type: 0,
title: false,
content: message,
closeBtn: false,
shadeClose: false,
isMessage: true,
shade: false,
time: 1000,
btn: false,
};
return layer.create(option, defaultOption, callback);
},
// 加载
load: (load: number, option?: any, callback?: Function) => {
let defaultOption = {
type: 3,
load: load,
anim: 5,
isOutAnim: false,
shadeClose: false,
};
return layer.create(option, defaultOption, callback);
},
// 确认
confirm: (msg: string, option?: any, callback?: Function) => {
let defaultOption = {
type: 0,
content: msg,
shadeClose: false,
};
return layer.create(option, defaultOption, callback);
},
// 创建弹出层
create: (option: any, defaultOption: any, callback?: Function) => {
// 销毁定时
let timer: NodeJS.Timeout;
// 聚合配置 Opt
const options = mergeOption(option, defaultOption);
// 创建容器 Dom
const modalContainer = createContainer();
options.id = modalContainer;
// 创建虚拟 Dom
const modalInstance = h(
LayLayer,
{
...options,
isFunction: true,
destroy() {
clearTimeout(timer);
modalInstance.component?.exposed?.close();
setTimeout(() => {
render(null, modalContainer);
// 清空 dom
if (document.body.contains(modalContainer)) {
document.body.removeChild(modalContainer);
}
}, 2000);
delInstance(modalContainer.id);
},
},
modalChildrenVNode(options.content)
);
modalInstance.appContext = options.appContext || layer._context;
// 将虚拟 dom 渲染到 dom 容器
render(modalInstance, modalContainer);
// 调用 open 函数
modalInstance.component?.exposed?.open();
// 延时 time 销毁
if (defaultOption && defaultOption.time != undefined) {
timer = setTimeout(() => {
modalInstance.component?.exposed?.close();
if (callback) callback(modalContainer.id);
setTimeout(() => {
render(null, modalContainer);
if (document.body.contains(modalContainer)) {
document.body.removeChild(modalContainer);
}
}, 2000);
// 销毁实例
delInstance(modalContainer.id);
}, defaultOption.time);
}
// 维护实例
addInstance({ modalContainer, modalInstance });
// 返回实例
return { modalContainer, modalInstance };
},
// 关闭弹出层
close: (instance: any) => {
if (instance != null && isExist(instance.modalContainer.id)) {
instance.modalInstance.component?.exposed?.close();
setTimeout(() => {
render(null, instance.modalContainer);
if (document.body.contains(instance.modalContainer))
document.body.removeChild(instance.modalContainer);
}, 2000);
}
// 销毁实例
delInstance(instance.modalContainer.id);
},
// 关闭所有弹出层
closeAll: () => {
layerInstance.forEach((item: any) => {
item.modalInstance.component?.exposed?.close();
setTimeout(() => {
render(null, item.modalContainer);
if (document.body.contains(item.modalContainer))
document.body.removeChild(item.modalContainer);
}, 2000);
});
// 清空实例
cleanInstance();
},
// 重置位置
reset: (instance: any) => {
instance.modalInstance.component?.exposed?.reset();
},
};
// 全局安装
const install = (app: App, options?: InstallOptions): void => {
layer._context = app._context;
app.component(LayLayer.name, LayLayer);
app.config.globalProperties.$layer = layer;
if (options) {
app.provide(zIndexKey, options.zIndex);
}
};
export { layer, LayLayer };
export default { install };
import "./theme/index.css";