@fesjs/fes-design
Version:
fes-design for PC
142 lines (139 loc) • 3.99 kB
JavaScript
import { defineComponent, ref, onBeforeUnmount, cloneVNode, createVNode, TransitionGroup, createApp, onMounted, mergeProps } from 'vue';
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled, ExclamationCircleFilled } from '../icon';
import { useTheme } from '../_theme/useTheme';
import { getFirstValidNode } from './vnode';
const _excluded = ["getContainer"];
let seed = 0;
const now = Date.now();
function genUid() {
return `notice_manager_${now}_${seed++}`;
}
const Notification = defineComponent({
props: {
maxCount: Number,
transitionName: String
},
setup(props) {
const notices = ref([]);
const timers = new Set();
function remove(key) {
const index = notices.value.findIndex(item => item.key === key);
const notice = notices.value[index];
if (notice) {
var _notice$afterRemove;
notices.value.splice(index, 1);
(_notice$afterRemove = notice.afterRemove) === null || _notice$afterRemove === void 0 || _notice$afterRemove.call(notice);
}
}
function append(notice) {
if (!notice.key) {
notice.key = genUid();
}
if (props.maxCount && notices.value.length >= props.maxCount) {
notices.value.shift();
}
notices.value.push(notice);
if (notice.duration > 0) {
const timer = setTimeout(() => {
remove(notice.key);
clearTimeout(timer);
}, notice.duration * 1000);
timers.add(timer);
}
return notice;
}
onBeforeUnmount(() => {
// 清理所有未触发的定时器
timers.forEach(timer => {
clearTimeout(timer);
});
timers.clear();
});
return {
notices,
append,
remove
};
},
render() {
const {
notices,
transitionName
} = this;
const children = notices.map(notice => {
let vNode = typeof notice.children === 'function' ? notice.children() : notice.children;
vNode = getFirstValidNode([vNode]);
if (vNode) {
return cloneVNode(vNode, {
key: notice.key
});
}
});
return createVNode(TransitionGroup, {
"name": transitionName,
"tag": "div"
}, {
default: () => [children]
});
}
});
function createManager(opt) {
return new Promise(resolve => {
const {
getContainer
} = opt,
props = _objectWithoutProperties(opt, _excluded);
const div = document.createElement('div');
if (getContainer) {
const root = getContainer();
root === null || root === void 0 || root.appendChild(div);
} else {
document.body.appendChild(div);
}
const app = createApp({
setup() {
useTheme();
const notificationRef = ref();
const instance = {
append: noticeProps => notificationRef.value.append(noticeProps),
remove: key => notificationRef.value.remove(key),
destroy() {
app.unmount();
if (div.parentNode) {
div.parentNode.removeChild(div);
}
},
exited() {
// 容器是否存在
if (!getContainer) {
return true;
}
try {
if (!getContainer()) {
instance.destroy();
return false;
}
} catch (error) {
instance.destroy();
return false;
}
return true;
}
};
onMounted(() => resolve(instance));
return () => createVNode(Notification, mergeProps({
"ref": notificationRef
}, props), null);
}
});
app.mount(div);
});
}
const iconComponentMap = {
info: InfoCircleFilled,
success: CheckCircleFilled,
error: CloseCircleFilled,
warning: ExclamationCircleFilled
};
export { createManager, iconComponentMap };