pinia 是为任务看板设计的单一数据源解决方案,通过结构化 store 管理嵌套的列与卡片状态,封装拖拽排序逻辑于 actions,结合 storetorefs 和 computed 保障响应式性能,并借助持久化插件实现跨端数据同步。

在任务看板(如 Kanban 风格的 Trello 类应用)中,列(Column)和卡片(Card)天然具有跨组件、跨页面的共享需求:拖拽排序要实时同步、新增卡片需全局刷新、列宽折叠状态要持久化、不同视图(看板/列表/日历)共用同一份数据。Pinia 正是为此类场景设计的——它让看板状态变成一个可响应、可调试、可持久化的「单一数据源」。
定义结构化看板 Store
看板状态不是扁平对象,而是嵌套层级:列数组 → 每列含卡片数组 → 卡片含标题、描述、截止时间、标签等。用 defineStore 显式建模更清晰:
- state 中用 ref 声明 columns: Column[],每个 Column 包含 id、title、order、cards: Card[]
- cards 本身也用 ref 或 reactive 封装,确保增删改触发响应(Pinia 的 state 默认响应式)
- 避免直接用普通对象或数组字面量,否则新增属性或索引赋值可能丢失响应性
拖拽排序逻辑封装在 actions 中
看板最核心交互是卡片拖拽重排——跨列移动、同列上下调整。这些操作涉及多个状态联动,必须收口到 actions:
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
- addCardToColumn(columnId, card): 插入卡片并更新该列 cards 数组
- moveCard(cardId, fromColumnId, toColumnId, positionIndex): 删除原列卡片 + 插入目标列指定位置
- updateCardOrder(columnId, newOrderIds): 批量重排,仅更新 cards 顺序不触发渲染抖动
- 所有 action 内部用 this.columns 直接修改,无需 commit/mutation,也不建议 $patch 大量字段
保持组件内响应式读取不掉帧
看板组件通常渲染几十个卡片,频繁解构 store 会导致响应性断裂或性能下降:
- 用 storeToRefs 解构 columns,保证列列表响应更新
- 卡片列表用 computed 缓存:const visibleCards = computed(() => store.columns.flatMap(c => c.cards))
- 避免在模板中写 v-for="card in store.columns[0].cards" —— 这会绕过响应追踪,应先解构再使用
- 对高频更新字段(如卡片拖拽中的临时位置),可用独立 ref + watch 同步到 store,减少主 store 频繁变更
持久化与多端兼容处理
看板数据用户极其敏感,刷新不能丢,但小程序/桌面端存储机制不同:
- 装 pinia-plugin-persistedstate,配置 key: 'kanban-store',只持久化 columns 字段(排除 loading 状态等临时字段)
- 跨端时判断环境:if (typeof localStorage !== 'undefined') 使用 localStorage;小程序用 uni.setStorageSync
- 路由切换回看板页时,在 onActivated 或 onShow 中调用 store.refreshFromStorage() 主动拉取最新状态,防止后台切前台后数据陈旧
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









