import type { VNode } from 'vue';
|
import Taro from '@tarojs/taro';
|
|
export type PortalNode = VNode | VNode[];
|
|
export type State = {
|
portals: Array<{
|
key: number;
|
children: PortalNode;
|
}>;
|
};
|
export type PortalManagerState = {
|
portals: Array<{
|
key: number;
|
children: PortalNode;
|
}>;
|
};
|
|
export type PortalMethods = {
|
mount: (children: PortalNode) => number;
|
update: (key: number, children: PortalNode) => void;
|
unmount: (key: number) => void;
|
};
|
|
export type Operation =
|
| { type: 'mount'; key: number; children: PortalNode }
|
| { type: 'update'; key: number; children: PortalNode }
|
| { type: 'unmount'; key: number };
|
|
export const PortalContextKey: InjectionKey<PortalMethods> = Symbol('PortalContextKey');
|
|
export function usePortalContext() {
|
return inject(PortalContextKey);
|
}
|
|
export function getUniqueKey(key: string) {
|
const router = Taro.getCurrentInstance().router;
|
const prefix = router.path;
|
return `${prefix}_${key}`;
|
}
|
|
// events
|
export const addType = 'ADD_PORTAL';
|
export const removeType = 'REMOVE_PORTAL';
|
|
export const TopViewEventEmitter = new Taro.Events();
|
|
class PortalGuard {
|
private nextKey = 10000;
|
add = (render: (_key: number) => PortalNode) => {
|
const key = this.nextKey++;
|
const node = render(key);
|
TopViewEventEmitter.trigger(getUniqueKey(addType), node, key);
|
return key;
|
};
|
remove = (key: number) => {
|
TopViewEventEmitter.trigger(getUniqueKey(removeType), key);
|
};
|
}
|
/**
|
* portal
|
*/
|
export const portal = new PortalGuard();
|
|
export type PortalManagerInstance = {
|
mount: (key: number, children: PortalNode) => void;
|
update: (key: number, children: PortalNode) => void;
|
unmount: (key: number) => {
|
key: number;
|
children: PortalNode;
|
}[];
|
};
|