iter(g304): 配方补可排序检查单(句柄式拼装)
This commit is contained in:
@@ -407,6 +407,30 @@ const panel = h('div', { class: 'review' },
|
||||
- `codeBlock` 的行号不参与复制,`copyButton` 直接读原文,所以「复制出来的代码」永远干净。
|
||||
- 差异行多了给 `diffView` 外层限定高度(或放进抽屉),否则长差异会把审阅按钮挤出视口。
|
||||
|
||||
## 配方 19:可排序的检查单(拖拽 + 键盘搬位 + 顺序回写)
|
||||
|
||||
```ts
|
||||
const steps = ['需求评审', '接口联调', '灰度发布', '线上回归'];
|
||||
const order = signal(steps); // 顺序唯一真相:组件与下方摘要读同一个信号
|
||||
const list = sortableList({
|
||||
items: steps, // 文案即排序键,要求唯一
|
||||
value: order,
|
||||
onChange: (next) => toast.success(`已调整:${next[0]} 置顶`),
|
||||
});
|
||||
card({ title: '发布检查单(可拖动,Alt+↑↓ 键盘搬位)' },
|
||||
list.el, // 返回的是句柄不是节点:忘了 append(el) 页面上一片空白
|
||||
h('p', { class: 'desc' }, () => order().map((t, i) => `${i + 1}. ${t}`).join(' ')),
|
||||
button({ label: '把「灰度发布」置顶', variant: 'ghost', onClick: () => list.move(2, 0) }),
|
||||
);
|
||||
```
|
||||
|
||||
要点:
|
||||
- `sortableList` 返回 `{ el, move, order }` 句柄(与 `form` / `virtualList` 同类):节点在 `el` 上,业务侧要改顺序用 `move(from, to)`,读当前顺序用 `order()`。
|
||||
- 顺序只存一份:`value` 信号同时喂组件与摘要 / 上报逻辑,否则会出现「界面拖了、提交的仍是老顺序」。
|
||||
- `move()` 与拖拽走同一条提交路径(都会触发 `onChange`),所以「置顶 / 上移」按钮不必另写状态同步;越界下标静默忽略,不用自己判边界。
|
||||
- 拖到边缘不会自动滚动:条目多到一屏放不下时改用筛选或上下移按钮,不要指望拖出视口;跨列表搬运用两个实例各持一个信号。
|
||||
- 条目文案要唯一——重名会让「谁被搬走了」失去参照,需要重复内容时把序号拼进文案(`'确认条款 #1'`)。
|
||||
|
||||
## 通用约定
|
||||
|
||||
- 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。
|
||||
|
||||
Reference in New Issue
Block a user