layui/package/layer/src/index.ts

264 lines
6.9 KiB
TypeScript
Raw Normal View History

2022-04-05 02:31:31 +00:00
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, removeNotifiyFromQueen } from "./utils";
2022-04-05 02:31:31 +00:00
// 实例队列
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) {
2022-04-05 02:31:31 +00:00
b = true;
}
});
return b;
};
2022-06-20 14:41:03 +00:00
const findById = (id: any) => {
let instance = null;
layerInstance.forEach((item: any, index: number) => {
if (item.modalContainer.id === id) {
instance = item;
}
});
return instance;
};
2022-04-05 02:31:31 +00:00
// 聚合 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);
},
// 消息
2022-04-20 01:48:35 +00:00
msg: (message: string, option?: any, callback?: Function) => {
2022-04-05 02:31:31 +00:00
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);
},
// 加载
2022-04-20 01:48:35 +00:00
load: (load: number, option?: any, callback?: Function) => {
2022-04-05 02:31:31 +00:00
let defaultOption = {
type: 3,
load: load,
anim: 5,
isOutAnim: false,
shadeClose: false,
};
return layer.create(option, defaultOption, callback);
},
// 确认
2022-04-20 01:48:35 +00:00
confirm: (msg: string, option?: any, callback?: Function) => {
2022-04-05 02:31:31 +00:00
let defaultOption = {
type: 0,
content: msg,
shadeClose: false,
};
return layer.create(option, defaultOption, callback);
},
//图片预览
photos: (option: any, callback?: Function) => {
2022-06-25 12:12:12 +00:00
if (typeof option === "string") {
option = {
2022-06-25 12:12:12 +00:00
imgList: [{ src: option }],
};
}
let defaultOption = {
type: 5,
anim: 2,
startIndex: 0,
isOutAnim: true,
shadeClose: true,
2022-06-25 12:12:12 +00:00
shadeOpacity: "0.7",
};
return layer.create(option, defaultOption, callback);
},
//通知
notifiy: (option: any = {}, callback?: Function) => {
option.shade = false;
option.type = 6;
let defaultOption = {
offset: "rt",
time: 2000,
area: "auto",
};
return layer.create(option, defaultOption, callback);
},
2022-04-05 02:31:31 +00:00
// 创建弹出层
2022-04-20 01:48:35 +00:00
create: (option: any, defaultOption: any, callback?: Function) => {
2022-04-05 02:31:31 +00:00
// 销毁定时
let timer: NodeJS.Timeout;
// 聚合配置 Opt
const options = mergeOption(option, defaultOption);
// 创建容器 Dom
const modalContainer = createContainer();
2022-06-20 14:41:03 +00:00
options.id = modalContainer.id;
2022-04-05 02:31:31 +00:00
// 创建虚拟 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 &&
defaultOption.time != 0
) {
2022-04-05 02:31:31 +00:00
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);
//Notifiy特殊处理
if (options.type === 6) {
removeNotifiyFromQueen(options.id);
}
2022-04-05 02:31:31 +00:00
}, defaultOption.time);
}
// 维护实例
addInstance({ modalContainer, modalInstance });
// 返回实例
2022-06-20 14:41:03 +00:00
return modalContainer.id;
2022-04-05 02:31:31 +00:00
},
// 关闭弹出层
2022-06-20 14:41:03 +00:00
close: (id: any) => {
if (id != null && isExist(id)) {
// 找到这个实例
const instance: any = findById(id);
2022-04-05 02:31:31 +00:00
instance.modalInstance.component?.exposed?.close();
setTimeout(() => {
render(null, instance.modalContainer);
2022-06-20 14:56:07 +00:00
if (document.body.contains(instance.modalContainer))
document.body.removeChild(instance.modalContainer);
2022-04-05 02:31:31 +00:00
}, 2000);
}
// 销毁实例
2022-06-20 14:41:03 +00:00
delInstance(id);
2022-04-05 02:31:31 +00:00
},
// 关闭所有弹出层
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";