useTheme
明暗档的单一入口。读写用户选择、解析出当前生效档写进 html[data-theme],并同步 color-scheme
——滚动条、下拉、日期选择这些原生控件不吃 --ui-* token,只认它。
XThemeToggle 只是它的一个操作面,同页放几个都是同一份状态。
基础
返回值
| 名称 | 类型 | 说明 |
|---|---|---|
preference | Ref<'light' | 'dark' | 'auto'> | 用户的选择,可写;auto 如实保留 |
resolved | Readonly<Ref<'light' | 'dark'>> | 当前真正生效的档,auto 时跟随系统 |
isDark | ComputedRef<boolean> | resolved === 'dark' |
system | ComputedRef<'light' | 'dark'> | 系统外观本身 |
toggle() | () => void | 在明暗间翻转,落到一个明确档位(不再是 auto) |
setHostTheme(theme) | (theme?: 'light' | 'dark') => void | 嵌入协议用:宿主指定这一页显示哪档,不持久化、不改用户偏好;传 undefined 撤销 |
选择与生效档要分开取:跨窗口下发主题(比如 Console 把档位交给 iframe 里的管理子站)必须传
resolved,把 auto 原样传过去等于让对方回落它自己的默认档。
全站共享
缺省时偏好存在可注册域的 Cookie(xwink-ui-theme)上,而不是 localStorage:localStorage 按源隔离,
console / chat / home / uc 各存一份;Cookie 按域共享,任何一个站点切换,其它站点在回到前台时跟上
(支持 cookieStore 的浏览器实时)。可注册域由逐级试写 Cookie 探测,本地 localhost 的 Cookie 不分端口,
开发环境同样全站一份。旧的 xwink-ui:theme localStorage 偏好在首次读取时迁移过去。
另存一份 xwink-ui-theme-resolved(上次生效档,只有 light / dark),SSR 宿主靠它在服务端就渲染出
正确档位,跟随系统时也一样;用户在两次访问之间改了系统设置才会有一次误差,客户端接管后纠正。
Nuxt 宿主启用 @xwink/ui/nuxt 即全部接好,不再各写首帧脚本或在 htmlAttrs 里写死档位:
- head 注入首帧脚本,挂载前按 Cookie 写好
data-theme(全新访客按系统); - 客户端插件先于其它插件初始化
useTheme,地址上带宿主theme参数(嵌入协议)时改为宿主覆盖; - SSR 宿主的服务端插件读 Cookie,把
data-theme渲染进 HTML,并让本次请求的useTheme按该档 计算;渲染用的档位放在 payload 的UI_SSR_THEME_STATE_KEY里,挂载前需要与服务端一致的组件按它出。
不需要接管时 xwinkUi: { theme: false }。
选项
| 选项 | 说明 |
|---|---|
storageRef | 已有的可写来源(如后端偏好接口响应里的 ref);给了它就不碰共享 Cookie |
storageKey | null 表示不持久化;显式给了键而没给 storage 时存 localStorage(不跨站共享) |
storage | 换掉存储本身(sessionStorage 或自定义实现) |
fallback | 没有已存偏好时的档位,缺省 auto |
// 明暗档挂到账号上:值由接口响应驱动,异步到达也会自动生效
useTheme({ storageRef: preferencesFromApi.themeMode })
单例与调用时机
内部用 VueUse 的 createSharedComposable + useColorMode:首次调用时的 options 决定整页配置,
之后的调用只是取用。@xwink/ui/nuxt 的插件已在最早时机按缺省配置调过一次,要换存储口的宿主关掉
模块的 theme 接管后在自己的插件里先调。服务端每次调用都是独立实例,不会串请求。
切换时抑制过渡来自 useColorMode。