TOGGLE3:动作栏里的三态分段控件 —— Dev/Staging/Prod、Light/Dark/Auto
一个按钮是「点击 → 执行」。一个选择框是「从 N 个里选一个」。那当你想要「三个已知状态」的时候 —— 因为你有 Dev/Staging/Prod,或 Light/Dark/Auto,或 Off/Default/Force-on?那就用 TOGGLE3(自 v2.13.25)—— 一个三态分段控件,每个状态有自己的颜色,状态切换时会运行 JS 代码。
为什么是单独一种类型,而不是 select / button?
| 类型 | 状态数量 | UX | 激活状态的 memory |
|---|---|---|---|
| BUTTON | 1(点击 = 运行) | 单个按钮 | 无 —— 触发即忘 |
| SELECT static | 2-N(下拉) | 点击后列表 | 有(dataset) |
| TOGGLE3 | 恰好 3 个 | 3 个并排按钮 | 有(索引 0/1/2) |
| INPUT / TEXTAREA | 自由文本 | 文本字段 | 有(el.value) |
三个状态恰好能排成一个「iOS 分段控件」模式 —— 3 个同时可见,一个激活,点击另一个则切换激活状态。没有下拉,没有意外。经典的移动端 UX。
第一个 TOGGLE3 动作 —— Light / Dark / Auto
给动作栏加一个 TOGGLE3 动作,带 3 个状态:
states[0] = { label: 'Light', value: 'light' }
states[1] = { label: 'Auto', value: 'auto' }
states[2] = { label: 'Dark', value: 'dark' }
defaultStateIdx: 1 // 首次访问为 Auto
在「Code」字段里:
// `value`、`stateIdx`、`stateLabel` 作为 const 注入在你代码之前。
const html = document.documentElement;
if (value === 'light') {
html.style.colorScheme = 'light';
html.removeAttribute('data-theme');
} else if (value === 'dark') {
html.style.colorScheme = 'dark';
html.setAttribute('data-theme', 'dark');
} else {
html.style.colorScheme = '';
html.removeAttribute('data-theme');
}
JUSTZIX.log(`主题 → ${stateLabel} (idx ${stateIdx})`);
点击「Dark」→ 动作修改 HTML,点击「Light」→ 代码带着新值重新运行。激活状态有满色(来自 action.color),非激活的则被淡化(来自 colorInactiveText)。
5 种颜色 —— 每个状态都有自己的视觉身份
自 v2.13.32 起,TOGGLE3 有 5 种可配置颜色(比任何其他动作类型都多):
| 属性 | 给什么上色 | 默认值 |
|---|---|---|
color | 激活状态的背景 | 动作的默认颜色 |
colorText | 激活状态的文字 | 白色 |
colorBg | 外层容器(整个分段)的背景 | 半透明黑 |
colorHover | 非激活状态的悬停背景 | 由 colorBg 经 filter:brightness |
colorInactiveText | 非激活状态的文字 | rgba(255,255,255,0.55) |
使用场景:Dev/Staging/Prod,其中每个激活状态有自己的语义颜色(绿 / 琥珀 / 红),但外层背景和非激活文字保持中性,以免混在一起。一个红色的「Prod」状态在视觉上格外醒目 —— 这正是重点。
使用场景 1 —— Dev/Staging/Prod 环境切换器
你有一个应用,同样的路径下有 3 个环境。到目前为止:手动改 URL,或者书签。带代码的 TOGGLE3:
// 每个状态的 value = 子域名
states[0] = { label: 'DEV', value: 'dev.app.com' } // color: green
states[1] = { label: 'STG', value: 'staging.app.com' } // color: amber
states[2] = { label: 'PROD', value: 'app.com' } // color: red
// 代码:
const newHost = value;
const path = location.pathname + location.search;
location.href = `https://${newHost}${path}`;
点击「PROD」→ 你跳到生产环境,同时保留路径 + 查询。memory 保存激活状态,所以刷新后你落在同一个环境(defaultStateIdx 只在首次访问时作为兜底起作用 —— memory 胜出)。
使用场景 2 —— 三态功能开关
你的应用从 localStorage 读取一个功能开关。三个现实的状态:「Off」(强制关)、「Default」(由服务器管理)、「Force on」(强制开)。
states[0] = { label: 'OFF', value: 'off' }
states[1] = { label: 'DEFAULT', value: 'default' }
states[2] = { label: 'FORCE', value: 'force' }
// 代码:
if (value === 'default') {
localStorage.removeItem('ff_newCheckout');
} else if (value === 'off') {
localStorage.setItem('ff_newCheckout', 'false');
} else {
localStorage.setItem('ff_newCheckout', 'true');
}
location.reload(); // 刷新后应用
JUSTZIX.log(`功能开关 → ${stateLabel}`);
QA 场景:2 秒内切换一个功能开关,查看视图,再切回默认。全程无需开发,也无需 DevTools 控制台。
使用场景 3 —— 通过 JZ.setValue 从另一个动作驱动
你有一个 TOGGLE3「主题」(Light/Auto/Dark)。还有另一个栏里的第二个 BUTTON 动作「🌙 夜间模式」,它应该是一段脚本,设置 Dark + 隐藏横幅 + 减小字号:
// BUTTON「夜间模式」—— 代码:
JZ.setValue('主题', 'dark'); // → 激活状态 idx 2 + 执行它的代码
document.body.style.fontSize = '14px';
document.querySelectorAll('.cookie-banner, .promo')
.forEach(el => el.style.display = 'none');
JUSTZIX.log('夜间模式已激活。');
可按 value 工作 —— JZ.setValue('主题', 'dark') 找到 value='dark' 的状态;或按 label —— JZ.setValue('主题', 'Dark') 不区分大小写;或按数字 —— JZ.setValue('主题', 2)。所有路径都收敛到同一个状态。
坑
- states.length 必须恰好是 3。isValidAction() 检查会在数组更小/更大时拒绝该动作。你需要 2 个状态?用带 2 个选项的 SELECT static 或一个 BUTTON 切换。需要 4 个以上?用 SELECT static。
- 状态里的 value 是可选的 —— 回退到
state.label。建议:用一个简短的符号化 value(像 'dev'/'stg'/'prod'),因为 label 可能含空格或 unicode 字符。 - memory 保存的是索引(0/1/2),不是 value。如果你后来重排了状态 —— 带旧 memory 的用户会落在不同的状态上。最佳实践:不要在已有的动作里重排状态。
- defaultStateIdx 只在首次访问时生效。如果用户已经用过该动作,memory 胜出 —— 即便你后来在编辑器里改了 defaultStateIdx,已有用户仍会看到他们之前的状态。
- UI 编辑器里 label 最多 5 个字符。渲染器接受更长的值,但分段控件紧凑的格式要求简短。
接下来做什么
TOGGLE3 是「UX 身份」最丰富的动作类型 —— 按状态着色、持久化、为三态决策内置作用域。另见 window.JZ 辅助函数,了解从其他动作程序化控制状态,以及 DEV/STG/PROD CSS 标记,作为环境切换器的视觉补充。
安装 JustZix —— 完全免费,没有服务器,无需账号。
为这篇文章评分
暂无评分 — 成为第一个。