4、框架适配与重构:从jQuery迁移到React/Vue、从AngularJS迁移到现代框架、组件化拆分策略
说实话,做界面移植最头疼的往往不是业务逻辑,而是框架层面的「代沟」。我见过太多团队,把jQuery代码直接塞进React项目里,结果状态管理乱成一锅粥。今天咱们就聊聊,怎么把老框架的代码,体面地迁移到现代框架上。
4.1 从jQuery到React/Vue:不只是换API
很多人觉得,jQuery到React就是换个写法。其实不然。jQuery是直接操作DOM,React/Vue是数据驱动视图。这个思维转变,才是最大的坎。
核心差异一句话:jQuery是你告诉DOM「怎么做」,React/Vue是你告诉框架「要什么」。
4.1.1 迁移策略:渐进式替换
我建议不要搞「大爆炸式重写」。风险太高,而且业务等不起。我习惯的做法是:
- 先搭架子:在现有页面中嵌入一个React/Vue根节点,比如
<div id="app"></div>。 - 逐个模块替换:把页面拆成独立功能块,比如搜索框、表格、弹窗,一个一个迁移。
- 共享状态用事件桥接:老代码和新框架之间,通过自定义事件或全局状态对象通信。
小技巧:迁移期间,可以用一个「包装器组件」把jQuery插件包起来。比如在React里用 useEffect 初始化jQuery插件,卸载时清理。这样能平滑过渡。
4.1.2 代码示例:jQuery vs React
看个实际例子。老代码是这样的:
// jQuery 方式
$('#btn').on('click', function() {
var count = parseInt($('#count').text()) + 1;
$('#count').text(count);
});
迁移到React后:
// React 方式
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<span>{count}</span>
<button onClick={() => setCount(c => c + 1)}>+1</button>
</div>
);
}
你看,React里没有 $('#count') 这种选择器了。数据在 state 里,视图自动跟着变。这个思维转变,说白了就是「别碰DOM,只管数据」。
4.2 从AngularJS迁移到现代框架
AngularJS(1.x)到Angular(2+)或者React/Vue,这个跨度更大。AngularJS的双向绑定和脏检查机制,跟现代框架的虚拟DOM、单向数据流完全是两码事。
我曾经接手过一个AngularJS项目,控制器里到处都是 $scope 和 $watch。迁移时我踩了不少坑,这里分享几个关键点。
4.2.1 告别$scope,拥抱组件化
AngularJS里,控制器和视图是通过 $scope 绑定的。现代框架里,组件自己管自己的状态。迁移时,我习惯把每个 controller 对应成一个组件。
| AngularJS 概念 | 现代框架对应 | 迁移要点 |
|---|---|---|
$scope |
组件状态(state/data) | 把 $scope 上的属性拆到组件的 data 或 state 里 |
$watch |
计算属性 / useEffect | 用 computed 或 useEffect 替代监听逻辑 |
$emit/$broadcast |
事件总线 / 状态管理 | 用 Vuex/Pinia 或 Redux/Zustand 替代 |
| 指令(directive) | 组件 / 自定义指令 | 大部分指令可以直接封装成组件 |
注意:AngularJS的 $digest 循环在现代框架里不存在。如果你在迁移后遇到视图不更新,多半是直接修改了对象属性而不是替换引用。记得用不可变数据的方式更新状态。
4.2.2 依赖注入的迁移
AngularJS的依赖注入很强大,但也容易让人写出「大控制器」。迁移时,我建议把服务(service)拆成独立的工具函数或 composables(Vue)/ hooks(React)。
// AngularJS 服务
app.service('UserService', function($http) {
this.getUser = function(id) {
return $http.get('/api/user/' + id);
};
});
// Vue 3 组合式函数
export function useUser() {
const getUser = async (id) => {
return await fetch('/api/user/' + id).then(r => r.json());
};
return { getUser };
}
你看,迁移后代码更轻量,而且不依赖框架的「魔法」了。测试也更好写。
4.3 组件化拆分策略
框架迁移只是第一步。真正让项目「活」起来的,是合理的组件化拆分。我见过不少项目,迁移完了,结果一个组件几千行代码,比老项目还难维护。
4.3.1 拆分的核心原则
我个人习惯用这几个维度来判断要不要拆:
- 单一职责:一个组件只做一件事。比如「用户头像组件」只管显示头像,别在里面写登录逻辑。
- 可复用性:如果一段UI在三个以上地方出现,就该抽成组件。
- 可测试性:组件越纯(不依赖外部状态),越好测。
我的经验:刚开始拆的时候,宁可多拆几个小组件,也别硬塞成一个。拆多了可以合并,拆少了重构成本更高。
4.3.2 拆分层次:从页面到原子
我习惯用「原子设计」的思路来分层。下面这张图能帮你理解:
4.3.3 拆分时的避坑指南
我曾经在一个项目里,把每个按钮都拆成独立组件,结果光按钮就有20多种变体,维护起来反而更累。后来我总结了几条经验:
- 别过度抽象:如果一个组件只有一处使用,而且逻辑简单,先别急着拆。等出现第二个使用者再说。
- Props 不要超过5个:如果一个组件的 props 超过5个,说明它可能承担了太多职责。考虑拆成子组件或用插槽(slot)。
- 状态提升要适度:把状态放到最近的共同父组件里。别一上来就扔到全局 store 里,那会让组件变得「不纯」。
我曾经踩过的坑:迁移时为了「好看」,把所有逻辑都塞进组件里,结果组件之间耦合严重。后来我改用「容器组件 + 展示组件」的模式——容器组件管数据和逻辑,展示组件只管渲染。这样一拆,代码清晰多了。
4.4 迁移后的验证与测试
框架迁移完,不代表就完事了。我习惯做三件事:
- 视觉对比:用像素级对比工具(比如 Percy)对比迁移前后的页面截图。
- 功能回归:把老项目的测试用例在新项目上跑一遍。如果没有测试,就手动走一遍核心流程。
- 性能基线:记录迁移前后的首屏加载时间、交互响应时间。现代框架不一定比jQuery快,但用户体验应该更好。
嗯,框架适配和重构这件事,说白了就是「用新思维解决老问题」。别想着一步到位,慢慢来,反而更快。