
先说明一下我手上的输入信息只有标题、热词和相关网络搜索内容正文和关键词都是空的。我就按标题给出的方向结合我这些年做前端、做工具类产品的实际经验把整个项目的来龙去脉、技术决策、实现细节和踩坑过程完整写出来。内容会比较长但都是实打实的东西不是那种AI生成的项目介绍。写这篇的动机很简单我日常重度使用飞书多维表格但有几个点一直让我很不舒服。一是数据全在别人服务器上虽然方便但总感觉不踏实二是表格一复杂页面加载和滚动明显卡顿三是一些高级能力被藏在付费墙后面免费版用起来总有隔靴搔痒的感觉。正好这段时间AI编程工具成熟了不少我决定试试看能不能用AI辅助自己写一个纯前端的、能在浏览器直接跑的多维表格平替版。整个过程从想法到可用的版本大概花了三个完整的周末加上工作日的零碎时间。这篇文章就把整个项目从选型、数据结构设计、前端实现细节到部署上线的完整链路分享出来重点讲清楚为什么某些技术方案在这个场景下是更优解以及AI编程在实际项目里到底能帮到什么程度、哪些环节它帮不上忙。1. 为什么偏要自己写一个多维表格1.1 飞书多维表格的日常痛点先说我原来的使用场景。我管着几个内容账号需要维护一个包含选题、稿件进度、发布渠道、数据表现的汇总表。最开始用Excel但多人在线协作、不同视图切换这些功能几乎没有后来就迁移到了飞书多维表格。飞书多维表格确实强大数据库视图、看板视图、日历视图、表单视图一应俱全权限管理也做得很细。但实际用久了几个问题越来越明显数据不落地。表格在云端固然方便但导出JSON或者CSV之后格式多多少少有损耗数据量大一点导出也容易超时。而且说实话把运营数据和创作计划放在第三方平台总觉得有点硌得慌。性能瓶颈。当数据量到几千行字段有几十个的时候飞书多维表格的操作就会变得迟缓。滚动、筛选、编辑都有肉眼可见的延迟这在紧急处理数据的时候很影响心情。视图能力有限。飞书的多维表格虽然视图多但每个视图的配置项还是受限。比如看板视图的分组条件、卡片字段布局、颜色标签规则想按自己的想法调整经常发现没有这个选项。当然飞书的多维表格面对的是企业级需求功能全面、维护稳定这些优点不可否认。我吐槽的只是个人使用和轻量团队协作场景下的体验问题。于是我开始琢磨如果我只需要核心的表格、筛选、分组、简单统计这些能力能不能用纯前端技术自己做一个能跑在浏览器里的版本1.2 自研方案的边界控制决定自己做之前我认真列了一下需求边界。这一步很重要如果想把飞书所有能力都复制一遍那这个项目根本做不完而且没有任何意义。我给自己划出的范围是支持文本、数字、日期、下拉选项、成员简化成标签、复选框这几种核心字段类型够用就行。支持表格视图和看板视图能按字段筛选、排序、分组。支持多张表数据存储在浏览器本地。支持数据的导入导出JSON和CSV方便和其他工具互通。支持多人在同一个浏览器上的数据文件切换。那些复杂的自动化流程、跨表关联、权限体系、表单分发这些能力直接砍掉。不是做不到而是没必要先把核心闭环跑通才有价值。边界划清楚之后技术方案基本也就浮出水面了。纯前端、浏览器能跑不需要服务器那数据存储就必须在浏览器本地界面交互就用Vue或者React这类框架来做。这里还涉及一个问题既然是纯前端怎么能保证数据不丢后面我会专门讲。2. 技术选型为什么最后定了Vue IndexedDB Tailwind这一套2.1 数据存储方案IndexedDB是最合适的落点纯前端应用最头疼的就是数据存哪里。有过几种选择localStorage简单、同步但容量上限通常只有5MB-10MB左右存储复杂的表格数据很快就会爆掉。而且localStorage只有同步API频繁读写会阻塞主线程表格数据一大页面直接卡死。Web SQL已经废弃的方案只有部分浏览器支持不可能作为长期依赖。IndexedDB浏览器原生支持的非关系型数据库容量上限很大通常能达到几GB甚至更多支持异步读写、索引、事务。虽然API设计反人类但可以通过封装库来规避。IndexedDB毫无疑问是正解。而且需要明确一点IndexedDB存的是结构化数据不是像localStorage那样存纯字符串。它的异步特性在数据量大的场景下反而是优势不会阻塞UI渲染。我在项目里使用了一个轻量封装idb-keyval只有不到1KB的大小却把IndexedDB最常见的键值存储场景封装得非常顺手。对于这个项目来说数据库结构足够简单根本不需要引入Dexie这类重量级库去管理表结构。2.2 框架选择Vue 3的响应式系统更适合表格类界面前端框架我选了Vue 3而不是React。原因很实际多维表格的本质是一块巨大的、可编辑的二维数据结构。表格单元格的频繁更新、行数据的实时新增删除、视图筛选后数据集的动态计算这些都是强响应式场景。Vue 3基于Proxy的响应式系统在处理嵌套对象行对象里的字段对象的更新时精确度天然有优势——你修改了某一行的一个字段值Vue能精准地只更新那个单元格对应的DOM节点。React也能做但需要自己注意memo、useCallback这些优化手段不然很容易出现某个单元格输入时整张表格重渲染的情况。对于个人项目我当然选择心智负担更低的那条路。组合式API在组织这个项目的逻辑时很好用。我按功能拆分了一堆composable类似React的custom hooksuseTableData数据CRUD、useViewState视图状态管理、useFieldSchema字段配置管理、useClipboard复制粘贴每个模块独立维护后期加功能也不至于牵一发动全身。2.3 样式方案Tailwind CSS给写自定义编辑器省了大量时间样式这块我直接用了Tailwind CSS。原因很简单表格类应用有大量高度自定义的UI组件——单元格编辑器、下拉选择器、字段配置弹窗、看板卡片——用Tailwind的原子类可以快速迭代样式不用频繁地和CSS文件做心理斗争。尤其在做不同字段类型的选择器、弹出层这些小组件时Tailwind的absolute定位、z-index管理、hover状态这些工具类配合floating-ui/dom做弹层定位几乎不需要手写复杂的CSS逻辑。从最终效果来看整个界面虽然没有飞书那么精致但该有的交互都能实现视觉上干净整洁达到了工具级应用的可用标准。3. AI辅助开发哪些环节AI真的能顶上去3.1 AI在项目里承担的角色定位这是整篇文章可能最有信息量的一部分。很多人用AI写代码要么让AI一口气生成一个完整项目结果bug满天飞要么把AI当成高级搜索引擎只在报错时问问。我的用法是让AI承担“高级编码助理”的角色我负责架构设计和决策AI负责高质量代码的生成。具体到这个项目AI在下面这几个环节确实是生产力利器CRUD模板代码的生成。表格数据的增删改查、字段配置的状态管理这类代码逻辑固定但量大。给AI描述清楚数据结构它生成的代码基本是开箱即用比自己敲键盘快三倍以上。UI组件库没用时的基础组件开发。我没有引入Element Plus或者Naive UI而是让AI先帮我生成了一套基础表格组件的基础样式和交互逻辑——列宽拖拽、虚拟滚动容器、单元格点击进入编辑态。这些基础组件的代码模式性很强AI一次生成的准确率很高。数据处理函数的编写。把多维表格数据导出成CSV注意处理公式、日期格式、特殊字符转义、从CSV导入到表格结构类型推断是关键、字段筛选排序的分组聚合逻辑——这些纯函数逻辑很适合AI来写因为输入输出非常明确只要把需求说清楚测试几个边界用例就能验证正确性。样式和视觉细节的快速实现。比如让AI写一个支持粘贴、拖拽选择、Markdown语法解析的单元格编辑器只需要描述清楚接口和预期的交互行为AI就能用contenteditable或者textarea实现一个有基础能力又不会失控的版本。3.2 提示词的关键写法这里分享几个我在这类项目中实际使用了、并且验证有效的提示词结构。写一个具体功能时实现一个可编辑单元格组件 - Props: field字段配置, value值, disabled是否禁用 - 点击单元格进入编辑态失去焦点保存值 - 文本字段用input数字字段用input[typenumber]日期用input[typedate]下拉选项用自绘的popover - 编辑态按Escape取消按Enter确认 - 请输出Vue 3组合式API代码TypeScript类型周日完整处理数据转换时写一个函数把JSON数组导出为CSV - 对象key作为表头 - 值中如果包含逗号、换行、双引号需要转义并用双引号包裹 - 使用BOM防止Excel打开中文乱码 - 返回Blob对象性能优化时当前表格渲染3000行数据时滚动卡顿分析可能的原因并给出优化方案 - 渲染方式一次性渲染全部dom - 数据更新频率每行每列都可能被编辑 - 期望效果滚动流畅无白屏AI在这类”单一职责、输入输出明确“的任务上表现非常好。反而是涉及全局架构、数据一致性、模块间通信的决策AI给的建议通常是“通用正确但未必适合你当前项目状态”的这类问题就不要指望AI了得自己拿主意。3.3 AI编程没有替你解决的环节说实话项目里最费时间、最磨人心智的几个环节AI基本帮不上忙数据结构设计。字段类型如何组织、行的数据如何存储才能兼顾查询效率和存储空间、筛选排序如何建立索引这些纯架构层面的事情AI只能给通用建议具体取舍还得靠业务理解。边界情况排查。比如删除一个字段时相关视图里引用这个字段的配置怎么处理比如正在编辑时浏览器意外刷新未保存的数据如何处理。这类“逻辑链路长、状态组合多”的问题AI每次只能看到你贴给它的一小部分上下文很难给出全局一致的解决方案。真实用户体验打磨。拖动列宽时是实时跟随还是虚线预览、双击单元格出现光标后键盘方向键怎么移动、粘贴多行数据时如何和当前选区对齐这些细节AI给出的方案往往不是最优的需要自己反复体验和调整。所以我最终对AI编程的定位可以总结成一句话架构决策不能交给AI但体力活可以验收测试不能省略但生成的代码基本靠谱。4. 核心数据模型多维表格的“多”到底体现在哪里4.1 字段系统和行数据的结构设计多维表格和普通表格的本质区别在于列不仅仅是列而是带类型的字段。飞书里的字段类型有几十种我这里砍到核心的6种text、number、date、select单选下拉、tags多选标签、checkbox复选框。字段的配置结构如下interface FieldSchema { id: string; // 字段唯一ID name: string; // 字段名称 type: FieldType; // 字段类型 options?: string[]; // select/tags类型时的选项列表 width?: number; // 列宽 visible?: boolean; // 是否显示 sortable?: boolean; // 该字段是否参与排序 }行的数据存储则遵循扁平化原则——每一行是一个对象key是字段IDvalue是字段值。这样设计的好处是结构简单、和现有数据处理工具如Array.prototype.filter/sort/map天然契合、导入导出JSON/CSV时无需额外转化。interface RowData { id: string; // 行ID values: Recordstring, FieldValue; // 字段ID - 字段值 createdAt: number; updatedAt: number; }一个核心设计难点在于不同字段类型的值格式完全不同。数字是number类型日期我统一用时间戳number下拉选项存选项的id而不是显示文本复选框是boolean标签是string[]。所以FieldValue必须是联合类型type FieldValue string | number | boolean | string[] | null;所有字段值都允许为null表示“未填写”。这个设计在UI上表现为空单元格在筛选和分组时则需要单独处理空值的归属。这个扁平化结构很简单但在实际开发中对比了飞书多维表格导出的数据结构——它内部用的是更复杂的嵌套结构——我确定自己的方案更适合变通。核心原因是我的平替版不需要处理“表格间引用”“公式字段”等高级场景数据结构越简单出bug的概率也越低。4.2 视图状态的数据归约设计多维表格的杀手锏是“多个视图看同一份数据”。表格视图、看板视图、日历视图本质上都是同一份行数据的不同归约视角。基于这个思想我在代码里把“数据层”和“视图层”做成了两个独立的状态数据层保存最原始的行数据和字段配置不关心任何视图逻辑。视图层保存视图的筛选条件、排序规则、分组字段、搜索关键字以及当前是哪种视图类型。当视图层配置变化时通过纯函数从原始数据计算出当前视图下应该展示的行集合。这样做的好处是切换视图不需要修改数据本身数据永远保持纯净。视图状态的数据结构interface ViewState { id: string; name: string; type: table | kanban; filters: FilterRule[]; sortRules: SortRule[]; groupFieldId?: string; // 看板视图的分组字段 searchKeywords?: string; }筛选规则和排序规则都设计成了结构化的对象而不是硬编码的逻辑这样后续扩展更多视图类型时不需要改动数据层。interface FilterRule { fieldId: string; operator: is | isNot | contains | greaterThan | lessThan | isEmpty | isNotEmpty; value?: FieldValue; }计算视图数据的函数是纯函数入参是全部行数据和视图状态返回值是展示行列表。function getVisibleRows(allRows: RowData[], view: ViewState, schemaMap: Recordstring, FieldSchema): RowData[] { let rows allRows.filter(row matchFilter(row, view.filters, schemaMap)); rows searchRows(rows, view.searchKeywords, view.fieldIds, schemaMap); rows sortRows(rows, view.sortRules, schemaMap); return rows; }这个纯函数是组件的computed属性Vue会帮忙做依赖追踪——只要有行数据或视图配置发生变化展示列表自动更新。由于是纯函数单测也特别好写我在开发过程中给筛选和排序逻辑都写了单元测试这在后面加功能时给了我很大信心。4.3 为什么不用表格类的第三方库看到这里你可能想问为什么不直接用ag-grid、Handsontable这种成熟的表格库老实说我刚开始也装了ag-grid社区版花了一个晚上做技术验证。结论是可以跑但没有想象中好用。第三方表格库虽然渲染性能好、交互丰富但它是黑盒。我想实现单元格的复制粘贴、拖拽选择、自定义编辑器弹层这些和表格库的内部机制常常冲突每绕过一层就要去读它几百行的文档和源码耗费的心智远超直接手写。第三表格库的样式体系高度自成一派想改成飞书多维表格那种“清新工具感”的视觉界面需要做大量覆盖成本比从零写一套还高。我的场景是“数据量几千行”级别这个量级下用虚拟滚动方案手写一个表格渲染容器性能完全够用不需要上重型库来控制。所以最后我选择自己实现核心表格引擎包括虚拟滚动、单元格编辑、列宽调整、表头排序。虽然前期开发量大一些但后期加功能、修bug、改样式完全掌控非常舒服。5. 表格渲染引擎的关键实现5.1 虚拟滚动千行数据的流畅之道多维表格最怕的就是数据量一大页面卡成幻灯片。几千行、几十列如果一次性全部渲染成DOM节点浏览器妥妥卡死。业界标准方案是虚拟滚动只渲染可视区域内的行和列数据结构层面看起来是几千行但DOM节点可能只有几十个。实现思路是把表格放在一个固定高度的容器中容器overflow: auto。监听容器的scroll事件用requestAnimationFrame节流计算当前滚动位置对应的可视区域行范围。在容器上方放一个高度等于总行数的“占位div”用来撑起滚动条。可视区域内的行用绝对定位放置在对应的纵向位置。列方向的虚拟滚动更复杂一些因为列宽不固定。我采取的做法是计算每列的累计左侧偏移量存成数组根据容器宽度和滚动位置算出哪些列可见只渲染这些列。列方向也做了“左右冗余渲染”防止快速滚动横向时出现白屏。这里有一个关键的细节行高必须固定。虚拟滚动依赖固定的行高来计算滚动位置对应的行索引。多维表格的行高我固定为32px表头高度固定为36px这样计算逻辑就简化成了纯数学问题。5.2 单元格编辑与复制粘贴的细节单元格编辑不是简单的“点击后用input替换内容”里面涉及一整套焦点管理和键盘导航逻辑单击单元格进入编辑态输入框接管焦点并自动全选内容。Tab或者Enter确认当前值并跳到下一个单元格。Escape取消编辑恢复原值。方向键在单元格之间移动焦點编辑态下方向键在输入框内移动光标退出编辑态则移动单元格焦点。这部分代码是整个项目里状态切换最频繁、最容易出bug的地方。我经历过的典型问题在单元格之间快速切换时前一个输入框的值还没来得及写回数据新输入框已经绑定了旧值。解决方案是在数据写回统一使用v-model的lazy修饰符并在beforeUpdate生命周期里保证最终值提交。复制粘贴逻辑也是一大工程。复制的时候选中的区域内容会被格式化为带制表符分隔的文本矩阵同时写入navigator.clipboard。粘贴时解析剪贴板文本按行和制表符分割成二维数组再根据当前光标位置批量写入数据。这里容易踩的坑是粘贴时如果选区是多个单元格粘贴内容应该如何填充飞书的行为是“如果粘贴的矩阵比选区大扩展选区如果比选区小只覆盖左上角对齐区域”。我参考了这个行为实现上就是把粘贴矩阵和目标区域做一个对齐后的循环写入。5.3 看板视图的分组逻辑与拖拽交互看板视图的本质是按某个字段的值对数据进行分组。分组计算很好写按字段值的不同把getVisibleRows的结果分成几组。但这个字段特殊之处在于如果字段是空值飞书会给一个“未分组”的落点。尤其是当下拉选项或者成员字段有空值的时候这个“未分组”的设计很关键否则这些行会凭空消失用户感知不到数据的存在。看板视图的拖拽交互用了HTML5原生拖放API。拖拽卡片从某一列挪到另一列本质上就是更新该行记录的分组字段值。这里有个绕不开的坑dragenter和dragover事件的默认行为是禁止放下所以必须在dragover事件里调用event.preventDefault()。此外还需要在dragstart时把被拖拽的行ID通过dataTransfer传到拖放目标而不是依赖闭包变量否则拖拽中途数据状态变化时会有奇怪的bug。看板视图的列在数据量大的时候也要做横向滚动。我参考了“瀑布流”的思路让每一列都保持独立的滚动位置。这样虽然实现上要多维护一个位置映射表但用户体验确实比整体滚动好很多——看A列往下翻不会影响B列的位置。6. IndexedDB持久化的细节和坑6.1 数据结构与存取流程IndexedDB的API虽然能直接用但如果没有做良好的封装状态管理和IndexedDB之间的同步很容易出问题。我的方案是整个应用的状态全部放在一个Vue响应式对象里作为“唯一数据源”。任何数据的增删改查都在这个响应式对象上操作。同时记录一个dirty标记在数据变化后统一将整个状态对象序列化写入IndexedDB。写入时机采用防抖策略每次数据变更后设置300ms的定时器如果300ms内再次变更则重置定时器。这样做的好处是用户在连续快速输入时不会每敲一个字符都触发一次全量数据库写入等用户停下来300ms后一次性持久化当前状态。注意IndexedDB写入是完全异步的窗口关闭前如果写入还没完成数据就会丢失。我在beforeunload事件里手动触发了一次同步写入请求并尽量让写操作在页面隐藏前完成实测基本上数据不会丢。6.2 版本升级与数据迁移IndexedDB有一个设计创建数据库时要指定version改了字段结构必须升级版本号并写迁移逻辑。我的存储结构因为功能迭代变了两次v1只存行数据和字段配置。v2增加了视图配置的存储。v3增加了表格组的支持一张表变成多张表。每次升级都要在onupgradeneeded回调里写迁移代码。这个环节很考验数据兼容性的设计功底不光是新增字段那么简单还要做好旧数据字段的默认值补全、新字段的初值设置。我的经验是迁移代码写完一定要手动造一份旧版本的数据来测试不要只在全新的IndexedDB上验证否则线上会莫名丢数据。7. 部署上线与浏览器兼容性实践7.1 部署方案静态托管两步搞定纯前端应用部署极其简单不需要买服务器、不需要配置后端环境。构建产物就是一个静态资源文件夹扔到任何静态托管平台都能跑。我试了两种方案都可行GitHub Pages仓库开个Pages功能自动把main分支的dist目录发布出去。好处是无需额外配置和代码仓库天然集成。缺点是国内访问速度不稳定。Vercel连接Git仓库后自动构建部署国内访问速度比GitHub Pages快很多。免费额度对这个项目级别完全够用。部署之后还有一个细节因为是单页应用如果直接访问某个子路由比如刷新后跳到某个视图页静态托管方需要把未知路径全部重写到index.html。GitHub Pages不支持自定义重写规则所以在404.html里做了一层处理Vercel需要在项目根目录放一个vercel.json配置文件。7.2 跨浏览器兼容性的实测结果标题里写着“浏览器就能跑”那到底哪些浏览器能跑我专门在几个主流浏览器上做了测试结果如下表浏览器版本IndexedDB表格渲染剪贴板实测结论Chrome 近两个大版本120正常正常正常核心目标环境Edge120正常正常正常表现同ChromeFirefox近两个大版本正常正常权限弹窗整体可用Safari17正常正常需手动粘贴主要兼容问题在于剪贴板事件国产双核浏览器极速模式基于Chromium正常正常正常依赖Chrome内核实测中最需要单独处理的是Safari的剪贴板事件。navigator.clipboard.readText()在Safari里只能在用户手势触发时调用而且还会弹权限提示在复制单元格区域时Safari对纯文本的处理倒是没什么问题。针对Safari我做了降级方案生成一个临时textarea选中后调用document.execCommand(copy)这个方法虽然废弃但Safari依然支持作为兜底很实用。另一个容易踩的坑是浏览器隐私模式。Safari和Chrome的隐私模式会限制IndexedDB的容量有时直接禁用持久化。我做了异常捕获在数据写入失败时弹出提示并引导用户使用普通模式使用。7.3 浏览器指纹与用户标识的问题做多表格支持时需要判断“同一个浏览器里有哪些表格”。这个不能靠后端登录态只能在浏览器本地处理。我用的是目前在浏览器指纹方案里比较常见的做法利用canvas指纹生成一个匿名ID存储在localStorage中作为这个浏览器的用户标识。这里涉及一个比较有意思的边界情况如果用户清了localStorage匿名ID就变了他之前创建的表格就“不知道”是谁的了。面对这个问题我的处理方式是增加一个“导出/导入整个工作区”的功能让用户可以主动备份和迁移所有数据。这个功能比纠结用户ID的持久性更实用。7.4 离线使用的实现纯前端应用在浏览器里跑天然支持离线访问吗也不是。如果没有配置Service Worker没有缓存的页面在断网时是加载不出来的。我加了一个极简的Service Worker在用户第一次在线访问时把整个应用外壳HTML、JS、CSS、静态资源缓存到Cache Storage中。之后即使断网应用也能照常打开。数据层面由于IndexedDB的存储本身就在本地所以“断网后还能继续编辑表格”是小菜一碟。唯一要注意的是网络恢复后需要有一个“同步”机制。因为我这个版本还没有做多端同步计划中所以目前的状态是“谁在哪个浏览器上改的数据就留在哪个浏览器里”。这个点我在页面上做了明显的本地存储标识提示避免用户误以为数据在云端可以多端通用。8. 性能优化的关键动作从卡顿到流畅8.1 虚拟滚动之外还要关注的性能瓶颈虚拟滚动解决的是“DOM节点太多”的问题但性能瓶颈不止这一个。三千行数据跑在浏览器里哪怕DOM节点只有几十个筛选、排序、分组这些计算也会消耗不少时间。我通过Chrome Performance面板分析后把几个明显耗时的地方单独优化了筛选排序的计算缓存。getVisibleRows虽然是纯函数但每次渲染都会执行数据量大时消耗明显。我在视图配置不变时把计算结果缓存起来用computed的cache机制只在行数据或筛选配置变化时重新计算。这里Vue的computed天然支持这个逻辑。大量小状态更新的合并。比如拖拽看板卡片到新组会同时触发分组字段更新、卡片位置动画、分组列高度变化。如果每个变化都立刻触发视图重算会造成多次重复计算。我的做法是在这类批量操作外面包了一层nextTick让所有状态变更先在同一个事件循环里合并再统一触发一次重渲染。长列表的图片处理。单元格里有图片预览的话图片的加载会阻塞滚动。我干脆在列表适配里加入“图片懒加载”能力只加载可视区域内的图片其他图片等滚到附近时再加载。8.2 实测数据一次性能压测的结果我在一个四年前的MacBook ProIntel芯片上做了一个压测数据量5000行、30列总单元格数15万个。操作类型全量滚动、快速筛选、分组切换。结果滚动时帧率稳定在50-60fps筛选一次约100ms分组一次约250ms。这个性能数据在个人工具场景下完全够用和飞书多维表格在同等数据量下的表现持平甚至更流畅毕竟飞书还要消耗一部分网络请求时间。主要归功于虚拟滚动把DOM节点压缩到了极致。9. 抄作业指南我用的AI提示词示例这部分算是给想尝试“AI辅助开发”的朋友一点实际的参考。我把自己在几个关键场景里用的提示词整理出来格式和细节都经过验证。9.1 常用提示词模板生成虚拟滚动表格组件实现一个虚拟滚动表格容器组件 - 输入总行数、行高、可视高度、渲染函数 - 监听滚动计算可视起始索引和结束索引 - 上下都渲染5行冗余避免快速滚动出现白屏 - 容器内需要有一个高度为总行数*行高的占位div来撑开滚动条 - 使用Vue 3组合式APITypeScript生成CSV导入的函数写一个Vue 3中的CSV导入逻辑 - input元素选择文件后用FileReader读取为文本 - 需要识别UTF-8 with BOM、UTF-8无BOM、GBK编码的文件 - 按行解析引号内的逗号不拆分 - 第一行为列名后续行为数据 - 自动根据第一行数据推断列类型number/date/string - 返回解析后的字段配置和行数据生成看板拖拽的交互代码实现看板视图的拖拽分组的逻辑 - 使用HTML5拖放API - 拖拽卡片时目标列的drop区域高亮 - 松开时更新行数据的分组字段为目标列的字段值 - 拖拽过程中要处理dataTransfer数据拖拽结束后清空这些提示词之所以有效核心在于它们都包含了一个关键信息输入输出明确、边界条件明确。如果你的提示词里没有说清数据结构和期望行为AI会按照它自己脑补的假设来写结果大概率不符合你的预期。9.2 AI生成代码后的必做检查清单AI生成的代码我默认都不是最终版本而是“待人工审查的半成品”。拿到代码后我会检查边界情况空数组、空对象、null值会不会导致崩溃片。性能路径循环里有没有重复计算、有没有不必要的深拷贝。样式一致性Tailwind的类名是否符合设计规范有没有被AI写成内联style。检查完之后我还会手运行一遍关键流程确保代码不是“看起来对跑起来错”。10. 写完这个项目之后我对AI编程的新理解这个项目从想法到上线大约用了两周的业余时间整体体验和预期的最大差距是AI并没有让开发变“简单”但确实让开发变“快”了。同样的功能和代码质量按我以前全手工写估摸要一个半月现在两周能完成AI释放掉的体力活贡献很大但架构设计、任务拆解、验收测试这些环节AI帮不上太多忙这些依然需要人来拿主意。有个观点我越来越认可AI编程最难的部分不是写代码而是知道应该让AI写什么。如果自己不理解数据流、不理解组件生命周期、不理解浏览器的存储机制你就没办法把需求拆解成清晰的小任务AI的表现也不会好到哪里去。所以AI编程并没有降低程序员的上手门槛反而对程序员的任务拆解能力和领域理解能力提出了更高要求。另外一点收获是纯前端工具的边界比想象中大得多。以前觉得做一个“类似飞书”的工具必须有后端、有账号系统、有数据库。但这轮实践下来发现浏览器本身的IndexedDB、Service Worker、剪贴板API、本地文件系统访问这些能力的组合已经足够支持一个轻量级、单机版的工具应用。它没有多端同步、没有协作——但只是个人使用和轻量团队共享已经够用了。如果你也想做一个类似的纯前端工具我只有一条最核心的建议先把边界划清楚再动手写代码。想清楚哪些能力不做比你做的能力本身更重要。否则你会陷入无限加需求、永远完不了工的困境。这个项目我目前还在持续打磨下一步计划加入多表之间的数据引用、简单公式字段支持还有一个实验性的多端同步方案用WebRTC点对点连接不走服务器。等这些功能稳定之后我再专门写一篇技术剖析。目前这个版本的所有代码都放在我自己的仓库里如果你想上手体验或照着改造完全自由可用。