SPA 内联编辑与发布同步

SKILL开发
开发 未标注权限 许可证不明确
安装这个技能

Vue/Element Plus 单页应用里「表格内联编辑不生效」「发版后用户必须手刷」「跨页面数据不同步」的排查与修复方法论。出现 改完值变回原值 / 输入框打不进字 / 填完移开就变没 / 另一页看不到 时使用。

一句话选型结论

按资料字段整理

SPA 内联编辑与发布同步是开发类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类开发 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_1e183245/spa-edit-sync
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

开发
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_1e183245仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验2026-11-06上游最后核验时间 · 数据更新 2026-11-06
正文体量10.0 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
写代码与改 bug

按需求补代码、定位并修掉报错。

读仓库与生成改动

让模型读懂项目结构,再给出可落地的改动。

跑测试与排查故障

按现象排查问题,补测试用例并复跑。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在开发场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
SPA 内联编辑与发布同步当前 未标注权限 未标注 未标注 未标注 有
技能审查员 浏览器控制 ClawHub 市场 877.9 万 OpenClaw 有
Vercel React 最佳实践 浏览器控制 GitHub 仓库 849.1 万 Codex、Claude、Cursor 有
GitHub 代码协作 联网访问 ClawHub 市场 763.3 万 OpenClaw 有
网页设计指南 联网访问 GitHub 仓库 668.6 万 Codex、Claude、Cursor 有
本体论 只读 ClawHub 市场 663.7 万 OpenClaw 有

SKILL.md 全文

10.0 KB
模型实际读到的说明书原文,来自技能仓库

SPA 内联编辑与发布同步加固

解决单页应用中三类「数据看起来在、实际没存住」的问题:表格内联编辑回滚、发版后客户端拿不到新版、多视图数据不同步。

功能概述

这三类问题的共同特征是:不报错、不抛异常,只是安静地不生效。控制台干净、请求也返回 200,值就是没存住。所以排查不能靠看日志,必须按「值在哪一步被丢掉」逐层定位。

本 skill 给出:四条经真实返工验证的铁律、可直接套用的草稿模式代码骨架、跨视图同步方案、SPA 版本自感知实现、以及六个必测用例和一个可执行的探测脚本。

触发方式

命中任意一条即加载本 skill(用户原话常是下面这些):

  • 「这个单元格填不进去 / 打不了字」
  • 「改完一闪又变回原来的值」「显示已保存,刷新就没了」
  • 「填完鼠标一移开就变没」
  • 「筛一下之后刚改的又变回去了」
  • 「更新完还要我手动刷新才看到新的」
  • 「A 页面改的,B 页面看不到」

技术特征:Vue 3 + Element Plus 的 el-table 内联编辑、SPA(vite 构建)、keep-alive 多标签页。如果症状只在表格里出现、换成普通表单就正常,几乎一定是本 skill 覆盖的问题。

四条铁律

1. 表格行对象可能是副本,禁止 v-model 直连

只要表格 :data 来自 computed,且元素是 map / {...row} / recomputeParent(row, kids) 生成的,那么:

  • v-model="row.field" 写的是副本
  • 值能显示、能保存,但任何一次重算(筛选变化、切页重载、keep-alive 激活)副本重建 → 值回退
  • 用户感知:「改完一闪又没了」「这个字段根本不能编辑」

解法:草稿 + 显式提交(见下)。

2. 受控组件只给 :model-value 不回写,一定会回滚你

el-input / el-input-number / el-date-picker 都是受控组件。只传 :model-value 而不监听 @update:model-value 时,组件会按旧 prop 把用户输入重置。

组件 症状
el-input 打不进字(input.value 永远是空串)
el-input-number 能输入,失焦后被格式化成旧值
el-date-picker 日历点选无反应(选中值立刻被回滚)

结论:表格内联编辑优先用原生 <input>(无组件状态、无回滚)。必须用组件时,一律走 v-model + 草稿。

3. undefined(没草稿)≠ ''(用户清空)

这是最隐蔽的一条。草稿模式里写成:

const raw = (draft[key] ?? '').trim();   // ❌ 把两种语义合并了

提交时 delete draft[key] 会触发重渲染,组件/表格重新 patch 时又抛一次 blur。第二次读到空串,就当成「用户清空」——发出一个空值请求,把刚保存成功的值覆盖掉。

症状就是:填完鼠标移开就变没。

const draft = draftMap[key];
if (draft === undefined) return;          // ✅ 这次失焦没有新输入,直接返回
delete draftMap[key];

4. SPA 页面不会自己重新拉 index.html

index.html 只在「打开页面 / F5」时请求一次。服务端换了构建产物,已打开的标签页跑的仍是内存里的旧 JS——这不是缓存头配错,是 SPA 的固有行为。

解法:构建产出 version.json + <meta name="app-build">,前端定时比对(见 references/release-awareness.md)。

标准实现:草稿 + 显式提交

<script setup lang="ts">
import { reactive } from 'vue';

/** 草稿按业务主键存,与表格数据是否重建无关 */
const draft = reactive<Record<string, string>>({});

function onInput(key: string, e: Event): void {
  draft[key] = (e.target as HTMLInputElement).value;
}

function onBlur(row: Row, key: string): void {
  const value = draft[key];
  if (value === undefined) return;        // 铁律 3
  delete draft[key];
  const next = value.trim() === '' ? null : value.trim();
  if (next === (row.field ?? null)) return;   // 没变不写库
  row.field = next;
  void save(row);
}

async function save(row: Row): Promise<void> {
  await api(row);
  // 写回源数组:表格行是 computed 副本,只改副本会在下次重算时回退
  const src = rows.value.find((r) => r.id === row.id);
  if (src) src.field = row.field;
  bumpSyncRev();                          // 通知其它视图
}

/** 重载数据后清草稿,界面一律以库为准 */
function load(): Promise<void> {
  // ...
  for (const k of Object.keys(draft)) delete draft[k];
}
</script>

<template>
  <!-- 原生 input:DOM 自己管显示,只有草稿变化才回写,不会「卡在第一个字符」 -->
  <input
    :value="draft[row.id] ?? (row.field == null ? '' : String(row.field))"
    maxlength="200"
    @input="(e) => onInput(row.id, e)"
    @blur="onBlur(row, row.id)"
    @keyup.enter="(e) => (e.target as HTMLInputElement).blur()"
  />
</template>

要点:
- :value 读草稿(?? 只判 null/undefined,用户清空产生的 '' 会保留)
- @input 写草稿驱动渲染,输入才留得住
- @blur 才提交,避免每个字符一次请求
- @keyup.enter 主动 blur,符合表格编辑直觉
- 提交成功后写回源数组

跨视图同步

两个页面读同一份接口数据、各自被 keep-alive 缓存时,A 页保存后 B 页仍是旧值。

// stores/sync.ts
export const dataRev = ref(0);
export function bumpDataRev(): void { dataRev.value += 1; }
// 每个相关页面
let lastRev = dataRev.value;
onActivated(() => {
  if (dataRev.value === lastRev) return;
  lastRev = dataRev.value;
  void reload();
});

写操作成功后 bumpDataRev() 并同步自己的 lastRev(避免切回来重载自己)。

不要每次 onActivated 都重载——会丢树表展开状态、白等一次请求。

排查顺序(按命中率排)

  1. 打开 DevTools,直接在输入框里敲字符,看 input.value 有没有留下来
    - 留不住 → 铁律 2(受控组件回滚)
    - 留得住但失焦消失 → 铁律 3(重复 blur 空覆盖)
    - 一直正常但重算后回退 → 铁律 1(副本)
  2. 看 Network:请求发了几条?有没有 field=(空值)这种多余请求
    - 有 → 铁律 3
    - 完全没有 → @input 没触发,或字段绑错了行
  3. 看请求参数对不对:值是不是变成了「相邻列的文字拼接」
    - 是 → 列索引/选择器算错了(测试脚本常见),不是业务 bug
  4. 有筛选就清掉再试,对比有无筛选的差异
    - 只在有筛选时复现 → 铁律 1

验证要求(交付前必查)

  • 连续输入多字符,不是只测一个字符
  • 二次失焦:点进单元格 → 不输入 → 点走,值必须仍在
  • 主动清空仍然生效(不能因为守卫把「清空」也挡了)
  • 有筛选 + 清除筛选后值仍在
  • 刷新页面后与库一致
  • 另一页/另一视图同步可见

参考文件

  • references/inline-edit.md — 四类组件的回滚机制、正确写法对照、el-table 副本来源
  • references/release-awareness.md — SPA 版本自感知完整实现(vite 插件 + composable + 提示条)
  • references/verification-playbook.md — 真实数据安全验证、Playwright 探测、headless 与 headful 差异
  • scripts/probe-inline-edit.cjs — Playwright 探测脚本:逐字符输入、二次失焦、列定位,改配置即可跑

使用示例

场景一:报价表「提报成本」列,用户反馈填完一移开就变没

  1. 按「排查顺序」第 1 步,在输入框里敲 123,input.value 留得住 → 排除受控组件回滚
  2. 敲完点别处,值消失;Network 面板里出现两条请求:cost=123 和 cost=(空)
  3. 定位为铁律 3:onBlur 用 ?? '' 把「没有草稿」当成「用户清空」,重渲染后第二次 blur 把值写成 null
  4. 加守卫 if (draft[key] === undefined) return;,重新验证「二次失焦」用例通过

场景二:两个页面读同一份接口,A 页改了 B 页看不到

  1. 确认两页都在 keep-alive 内、各自持有一份接口数据
  2. 加全局修订号 dataRev,写操作成功后 bumpDataRev()
  3. 两页在 onActivated 里比对 dataRev !== lastRev 才重载
  4. 验证:用 hash 路由切页(location.hash = '#/other',不能用 page.goto 否则整页刷新测不出 onActivated)

场景三:每次构建完,同事都要手动刷新才能看到新功能

  1. 先排除缓存误判:vite preview 对 html/json 本来就发 no-cache,不是缓存头问题
  2. 加 buildVersionPlugin() 产出 version.json + 注入 <meta name="app-build">
  3. 前端每 30 秒比对,不一致则顶部提示并 8 秒后自动刷新
  4. 加 setDirty 上报,有未保存草稿或光标在输入框时暂停倒计时
  5. 验证时必须真跑一次 npm run build,只改 version.json 会造成误判

版本迭代记录

版本 日期 更新内容
v1.0.0 2026-10-29 首次发布:四条铁律、草稿模式代码骨架、跨视图同步、SPA 版本自感知、验证手册与探测脚本

常见问题

5 问
答案由本站依据条目字段整理
SPA 内联编辑与发布同步怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_1e183245/spa-edit-sync。安装方式为未标注。装完刷新技能列表或重开客户端。

SPA 内联编辑与发布同步支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

SPA 内联编辑与发布同步权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

SPA 内联编辑与发布同步收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

SPA 内联编辑与发布同步用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 2026-11-06。