Skip to content

Commit ad5f1a4

Browse files
committed
refactor(components): notify 采用 runWithOwner 处理上下文环境
1 parent 999ac81 commit ad5f1a4

3 files changed

Lines changed: 13 additions & 24 deletions

File tree

packages/components/src/notify/alert/root.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import type { JSX } from 'solid-js';
66

7-
import { useLocale, useOptions } from '@components/context';
87
import { Message, type Props as MessageProps, type Ref as MessageRef } from '@components/notify/message';
98

109
export type Props = Omit<MessageProps, 'transitionDuration' | 'closeAriaLabel'>;
@@ -15,7 +14,5 @@ export type Ref = MessageRef;
1514
* 警告框
1615
*/
1716
export function Root(props: Props): JSX.Element {
18-
const l = useLocale();
19-
const [opt] = useOptions();
20-
return <Message {...props} transitionDuration={opt.getTransitionDuration()} closeAriaLabel={l.t('_c.close')} />;
17+
return <Message {...props} />;
2118
}

packages/components/src/notify/message/message.tsx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import IconWarning from '~icons/material-symbols/error-rounded';
1111
import IconInfo from '~icons/material-symbols/info-rounded';
1212

1313
import { type BaseProps, type BaseRef, joinClass, type Palette, type RefProps } from '@components/base';
14+
import { useLocale, useOptions } from '@components/context';
1415
import styles from './style.module.css';
1516

1617
export const types = ['error', 'warning', 'success', 'info'] as const;
@@ -92,14 +93,6 @@ export interface Props extends BaseProps, RefProps<Ref> {
9293
* 在将当前组件从 DOM 中移除之前执行的操作,返回 true 将阻止后续的移除操作。
9394
*/
9495
onClose?: () => Promise<boolean | undefined>;
95-
96-
// 指定动画时间,因为在 notify 中使用了 render 渲染到 Portal 中,无法在 Message 中使用 useOptions 获取动画时长。
97-
transitionDuration: number;
98-
99-
/**
100-
* 关闭按钮的 aria-label,与 transitionDuration 相同的理由,不能放在 Message 组件内部。
101-
*/
102-
closeAriaLabel?: string;
10396
}
10497

10598
/**
@@ -108,6 +101,9 @@ export interface Props extends BaseProps, RefProps<Ref> {
108101
export function Message(props: Props): JSX.Element {
109102
props = mergeProps({ type: 'info' as Type }, props);
110103

104+
const l = useLocale();
105+
const [opt] = useOptions();
106+
111107
let rootRef: HTMLDivElement;
112108
let buttonRef: HTMLButtonElement;
113109

@@ -116,12 +112,12 @@ export function Message(props: Props): JSX.Element {
116112
return;
117113
}
118114

119-
if (!props.transitionDuration) {
115+
if (!opt.getTransitionDuration()) {
120116
return;
121117
}
122118

123119
rootRef.style.height = '0';
124-
await sleep(props.transitionDuration); // 待动画结束
120+
await sleep(opt.getTransitionDuration()); // 待动画结束
125121
rootRef.remove();
126122
};
127123

@@ -219,7 +215,7 @@ export function Message(props: Props): JSX.Element {
219215
type="button"
220216
class={styles['close-wrap']}
221217
ref={el => (buttonRef = el)}
222-
aria-label={props.closeAriaLabel}
218+
aria-label={l.t('_c.close')}
223219
>
224220
<IconClose onClick={close} class={styles.close} />
225221
</button>

packages/components/src/notify/notify/notify.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
// SPDX-License-Identifier: MIT
44

55
import { sleep } from '@cmfx/core';
6-
import type { JSX, ParentProps } from 'solid-js';
6+
import { type JSX, type ParentProps, getOwner, runWithOwner } from 'solid-js';
77
import { Portal, render } from 'solid-js/web';
88

99
import type { MountProps } from '@components/base';
1010
import { joinClass } from '@components/base';
11-
import { useLocale, useOptions } from '@components/context';
11+
import { useOptions } from '@components/context';
1212
import { Message, type Props as MessageProps, type Type } from '@components/notify/message';
1313
import styles from './style.module.css';
1414

@@ -123,9 +123,9 @@ export function NotifyProvider(props: ParentProps & MountProps): JSX.Element {
123123

124124
function init(): JSX.Element {
125125
const [opt, origin] = useOptions();
126-
const l = useLocale();
127126
let topRef: HTMLDivElement;
128127
let bottomRef: HTMLDivElement;
128+
const owner = getOwner();
129129

130130
notifyInst = async (
131131
title: string,
@@ -151,18 +151,14 @@ function init(): JSX.Element {
151151
type,
152152
duration: duration ?? opt.getStays(),
153153
closable: true,
154-
155-
// 通知可能放在 ThemeProvider 之外,所以使用 useOptions 的值。
156-
transitionDuration: opt.getTransitionDuration(),
157-
closeAriaLabel: l.t('_c.close'),
158154
};
159155

160156
switch (pos) {
161157
case 'top':
162-
render(() => <Message {...props} />, topRef);
158+
runWithOwner(owner, () => render(() => <Message {...props} />, topRef));
163159
break;
164160
case 'bottom':
165-
render(() => <Message {...props} />, bottomRef);
161+
runWithOwner(owner, () => render(() => <Message {...props} />, bottomRef));
166162
}
167163
};
168164

0 commit comments

Comments
 (0)