90 lines
2.6 KiB
Plaintext
90 lines
2.6 KiB
Plaintext
---
|
|
title: 接入外观偏好
|
|
description: 使用应用共享的偏好系统聚合外观定义与副作用。
|
|
order: 1
|
|
toc:
|
|
- id: provider
|
|
title: 聚合偏好
|
|
- id: effects
|
|
title: 注册副作用
|
|
- id: theme-style
|
|
title: 注入主题变量
|
|
- id: persistence
|
|
title: 持久化更新
|
|
---
|
|
|
|
## 聚合偏好 {#provider}
|
|
|
|
在应用边界构建一份完整的偏好定义。把外观、语言、快捷键等功能 package 的 definitions 合并,再创建默认值或从服务端加载初始值。
|
|
|
|
```tsx
|
|
import {
|
|
createDefaultPreferences,
|
|
PreferencesProvider,
|
|
} from "@workspace/preferences"
|
|
import {
|
|
appearancePreferenceDefinitions,
|
|
appearancePreferenceEffect,
|
|
} from "@workspace/appearance"
|
|
|
|
const preferenceDefinitions = {
|
|
...appearancePreferenceDefinitions,
|
|
...localePreferenceDefinitions,
|
|
}
|
|
|
|
const initialPreferences = createDefaultPreferences(preferenceDefinitions)
|
|
const preferenceEffects = [
|
|
appearancePreferenceEffect,
|
|
localePreferenceEffect,
|
|
] as const
|
|
|
|
export function Root({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<PreferencesProvider
|
|
effects={preferenceEffects}
|
|
initialPreferences={initialPreferences}
|
|
>
|
|
{children}
|
|
</PreferencesProvider>
|
|
)
|
|
}
|
|
```
|
|
|
|
只需要外观偏好切片时仍可使用 `defaultAppearancePreferences`;聚合多个 package 时,应优先以 definitions 作为生成完整默认值的单一来源。
|
|
|
|
## 注册副作用 {#effects}
|
|
|
|
`appearancePreferenceEffect` 组合了两个公开回调:`applyAppearancePreferenceEffect` 在浏览器绘制前更新文档类名和主题变量,`subscribeSystemThemePreferenceEffect` 在绘制后监听操作系统主题。把组合后的 effect 放进传给 `PreferencesProvider` 的稳定 `effects` 数组中。
|
|
|
|
## 注入主题变量 {#theme-style}
|
|
|
|
使用 `buildThemeStyleSheet` 生成浅色、深色以及跟随系统时使用的 CSS 变量。保留固定的元素 ID 后,外观 effect 可以在颜色偏好变化时更新同一个节点。
|
|
|
|
```tsx
|
|
import {
|
|
buildThemeStyleSheet,
|
|
THEME_STYLE_ELEMENT_ID,
|
|
} from "@workspace/appearance"
|
|
|
|
;<style
|
|
id={THEME_STYLE_ELEMENT_ID}
|
|
dangerouslySetInnerHTML={{
|
|
__html: buildThemeStyleSheet(themeLight, themeDark),
|
|
}}
|
|
/>
|
|
```
|
|
|
|
## 持久化更新 {#persistence}
|
|
|
|
共享的 `onPreferenceChange` 只在值实际变化时收到类型安全的 `{ key, value }`。应用可以把它交给服务端函数或 Cookie 写入器。
|
|
|
|
```tsx
|
|
<PreferencesProvider
|
|
effects={preferenceEffects}
|
|
initialPreferences={preferences}
|
|
onPreferenceChange={(update) => savePreference(update)}
|
|
>
|
|
{children}
|
|
</PreferencesProvider>
|
|
```
|