antd的message能通过方法调用,底层是如何实现的呢?
概览
- 导出支持调用的方法
- 管理消息队列
- 批量渲染
GIT地址:github.com/ant-design/…
源码解读
- 导出支持调用的方法
// 定义支持调用的方法,作为default导出
const methods: (keyof MessageMethods)[] = ['success', 'info', 'warning', 'error', 'loading'];
const staticMethods = baseStaticMethods as MessageMethods & BaseMethods;
methods.forEach((type: keyof MessageMethods) => {
staticMethods[type] = (...args: Parameters<TypeOpen>) => typeOpen(type, args);
});
export default staticMethods;
- 管理队列
function typeOpen(type: NoticeType, args: Parameters<TypeOpen>): MessageType {
// 管理队列
const result = wrapPromiseFn((resolve) => {
let closeFn: VoidFunction;
const task: OpenTask = {
type: 'open',
config,
resolve,
setCloseFn: (fn) => {
closeFn = fn;
},
};
taskQueue.push(task);
return () => {
if (closeFn) {
act(() => {
closeFn();
});
} else {
task.skipped = true;
}
};
});
flushNotice();
return result;
}
- 批量渲染
import { render } from 'rc-util/lib/React/render';
function flushNotice() {
// 定义实例
if (!message) {
const holderFragment = document.createDocumentFragment();
act(() => {
render(
<GlobalHolderWrapper
ref={(node) => {
const { instance, sync } = node || {};
// React 18 test env will throw if call immediately in ref
Promise.resolve().then(() => {
if (!newMessage.instance && instance) {
newMessage.instance = instance;
newMessage.sync = sync;
flushNotice();
}
});
}}
/>,
holderFragment,
);
});
return;
}
// Notification not ready
if (!message.instance) {
return;
}
// >>> Execute task
// 批量渲染
taskQueue.forEach((task) => {
const { type, skipped } = task;
// Only `skipped` when user call notice but cancel it immediately
// and instance not ready
if (!skipped) {
switch (type) {
case 'open': {
act(() => {
const closeFn = message!.instance!.open({
...defaultGlobalConfig,
...task.config,
});
closeFn?.then(task.resolve);
task.setCloseFn(closeFn);
});
break;
}
case 'destroy':
act(() => {
message?.instance!.destroy(task.key);
});
break;
// Other type open
default: {
act(() => {
const closeFn = message!.instance;
closeFn?.then(task.resolve);
task.setCloseFn(closeFn);
});
}
}
}
});
// Clean up
taskQueue = [];
}