Vue 3 迁移这件事,得一步步来。先摸清楚项目中哪些地方用了 jQuery 插件、把边界划清楚,然后用 Vue 指令把 select2、datepicker 这类轻量插件包起来,再用组合式函数封装 datatables 这种大家伙,最后一步到位替换成 Element Plus 的表格组件,让状态和 DOM 彻底跟 Vue 的响应式系统接轨。

想象一下:线上跑得好好的 jQuery 项目,要完整迁到 Vue 3 框架。业务逻辑不能改,交互行为不能丢,所有 DOM 更新、状态同步、插件调用都得老老实实接入 Vue 响应式体系——不能出现“页面刷新了数据却没变”或者“按钮点了但校验没反应”这种断裂感。
确认 jQuery 插件使用范围并锁定迁移边界
打开浏览器开发者工具,切换到 Sources 标签页,在全局搜索框里敲入 $.fn.datatable、$.fn.select2 或者 $.fn.datepicker,挨个看匹配结果所在的文件路径。
如果所有匹配都集中在 /legacy/order-list.html、/admin/user-form.js 这类带 legacy 或 admin 前缀的路径里,说明插件使用是模块化隔离的,按页面粒度推进就行;但要是 main.js 或者 utils/dom.js 里直接调了 $.datepicker(),那必须先抽出来单独封装——否则迁移后所有日期控件统统失效。
对每个插件绑定的 DOM 节点,记下它的选择器,比如 #order-table、.date-field、[data-role="select2"]。后续 Vue 组件要用同样的 ref 或 id 来接管,不然已有的 CSS 样式和自动化测试脚本会大面积报错。
用 Vue 3 指令封装 select2 / datepicker(过渡方案)
方法一:指令封装(适用于 select2、datepicker 这类单节点轻量插件)
在 src/directives/jqSelect2.js 里新建文件,导出一个默认对象,包含 mounted 和 beforeUnmount 两个钩子。mounted 里执行 $(el).select2(value),beforeUnmount 里必须调用 $(el).select2('destroy')——不 destroy 的话,内存泄漏不说,下次 mounted 时也会初始化失败。
组件模板里这么写:,直接绑在原 jQuery 用的同一个 上,无缝接管。
方法二:组合式函数封装(适用于 datatables 这类依赖复杂 DOM 结构的插件)
新建 src/composables/useJQueryDataTable.js,接收三个参数:tableRef(DOM ref)、data(ref 数组)、options(响应式配置)。内部用 onMounted 创建 DataTable 实例,用 watch 监听 data 变化并调用 table.clear().rows.add(newData).draw()。最后返回 table 实例和一个手动刷新方法。
彻底替换 datatables 为 Element Plus 表格组件
第一步:移除 jQuery 表格初始化代码
找到所有 $('#user-table').DataTable({ ... }) 的调用,整行删掉。同时删掉 HTML 里冗余的 手动结构——Vue 表格靠 ... v-for 动态生成列头。
第二步:安装并注册 Element Plus
执行 pnpm add element-plus,然后在 main.js 里调用 app.use(ElementPlus),确保全局能用 。
第三步:构建响应式表格骨架
新建 src/components/UserTable.vue,模板里用 , 通过 v-for 渲染列,prop 绑定字段名,label 显示标题。排序逻辑改用 @sort-change 事件捕获,不再依赖 DataTable 的 order 参数。
第四步:对接原有筛选与分页状态
原来 jQuery 插件里存在 window._tableState 或全局变量里的 currentPage、pageSize、searchKey,全部转为 ref,用 computed 计算出 filteredData。确保用户点击“搜索”按钮后,filteredData 更新 → 自动重绘 → 表格底部的 同步刷新总页数。
