如何用Webpack拆分过长的AngularJS Controller.js并按页面拆分?
AngularJS控制器按页面拆分方案(基于Webpack)
核心思路
将原document控制器按页面模块(创建报告、查看报告、保存确认、删除报告)拆分为独立的JS模块,通过Webpack的ES6模块导入机制组合,主控制器仅负责依赖注入、全局初始化和模块调度,解决代码冗余和可维护性问题。
文件结构调整
将原有单一控制器文件拆分为以下结构:
src/ ├── controllers/ │ ├── document.controller.js # 主控制器(入口) │ └── document/ │ ├── create-report.section.js # 创建报告模块 │ ├── report-view.section.js # 查看报告模块 │ ├── save-check.section.js # 保存确认模块 │ └── delete-report.section.js # 删除报告模块 └── services/ # 原有服务目录保持不变
拆分后代码实现
1. 主控制器(document.controller.js)
负责统一注入依赖、初始化全局数据,并调用各子模块初始化方法,传递所需资源:
console.log('load document'); // 导入拆分的子模块 import initCreateReport from './document/create-report.section'; import initReportView from './document/report-view.section'; import initSaveCheck from './document/save-check.section'; import initDeleteReport from './document/delete-report.section'; angular.module('app').controller('document', function ($scope, ItemService, UserService, ScopeService, $q) { $scope.$emit('changeTitle', 'document'); // 初始化服务实例 let itemService = ItemService(); let userService = UserService(); let scopeService = ScopeService(); let documentModel = itemService.document(); let userModel = userService.user(); let htmlModel = itemService.html(); // 全局共享变量 let html = { reportDoc: '', deleteForm: '', }; let users = []; let reportDoc = {}; $scope.docArray = []; // 初始化子模块,传递依赖与共享变量 let reportDocObj = initReportView($scope, scopeService, html, reportDoc); initCreateReport($scope, scopeService, html, reportDoc, reportDocObj); initSaveCheck($scope, scopeService, html); initDeleteReport($scope, scopeService, html); // 原有全局初始化逻辑 let url = 'static/html/testcase/document_temp.html'; let queue = [documentModel.list(), userModel.list(), htmlModel.get(url)]; $q.all(queue).then(function (result) { $scope.docArray = result[0].data; users = result[1].data; html = itemService.htmlArray[url]; }).catch(function (reason) { // 错误处理逻辑保留 }); });
2. 创建报告模块(create-report.section.js)
专注于创建报告页面的逻辑,接收主控制器传递的$scope、服务实例和共享变量:
export default function initCreateReport($scope, scopeService, html, reportDoc, reportDocObj) { // 初始化创建报告的ScopeService实例 let createReportDocObj = ScopeService('createReport') || scopeService.initialize( 'createReport', $('#background_document'), function () { let report = ''; return _.template(html.reportDoc)({ report: report }); }, false ); // 绑定到根$scope的方法 $scope.createDoc = function () { createReportDocObj.compile(true, {}); reportDocObj.scope.isLoading = false; initEditor(); }; // 编辑器初始化逻辑(内聚到当前模块) function initEditor() { // 原有编辑器初始化代码 } }
3. 查看报告模块(report-view.section.js)
处理查看报告的相关逻辑,返回reportDocObj供其他模块调用:
export default function initReportView($scope, scopeService, html, reportDoc) { // 初始化查看报告的ScopeService实例 let reportDocObj = ScopeService('reportDoc') || scopeService.initialize( 'reportDoc', $('#background_document'), function () { if (reportDocObj.scope.isLoading) return html.reportDoc; reportDocObj.scope.changed = false; if (!reportDoc.content) return; let report = reportDoc.content.html; return _.template(html.reportDoc)({ report: report }); }, false ); // 绑定子scope的方法 reportDocObj.scope.save = function () { // 原有保存逻辑 }; reportDocObj.scope.checkSave = function () { // 原有检查保存逻辑 }; reportDocObj.scope.download = function (editor) { // 原有下载逻辑 }; // 绑定到根$scope的方法 $scope.getDocument = function (id) { // 原有获取文档逻辑 }; // 返回实例给主控制器,供其他模块使用 return reportDocObj; }
4. 保存确认模块(save-check.section.js)
export default function initSaveCheck($scope, scopeService, html) { let checkSaveReportObj = ScopeService('checkSaveReport') || scopeService.initialize( 'checkSaveReport', $('#background_report'), function (args) { return _.template(html.checkSave)(args); }, false ); checkSaveReportObj.scope.submit = function () { // 原有提交逻辑 }; checkSaveReportObj.scope.cancel = function () { // 原有取消逻辑 }; }
5. 删除报告模块(delete-report.section.js)
export default function initDeleteReport($scope, scopeService, html) { let deleteReportObj = ScopeService('deleteReport') || scopeService.initialize( 'deleteReport', $('#background_report'), function (args) { return _.template(html.deleteForm)(args); }, false ); deleteReportObj.doc_id = undefined; $scope.deleteDoc = function (id) { // 原有删除触发逻辑 }; deleteReportObj.scope.submit = function () { // 原有删除提交逻辑 }; }
Webpack配置调整
确保Webpack能处理ES6模块语法,添加Babel转译规则:
module.exports = { // 其他配置... module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] } };
关键问题解决
- $scope引用:主控制器将根
$scope传递给子模块,子模块可直接使用根$scope绑定方法,或通过ScopeService创建的子scope操作,保证作用域一致性。 - 服务实例共享:主控制器统一注入并初始化所有服务,将实例传递给子模块,避免重复注入,确保服务实例的单例性。
- 模块间通信:通过主控制器作为中间层传递共享实例(如
reportDocObj),或利用AngularJS的$emit/$broadcast事件机制,或封装共享数据到专门的服务中。
内容的提问来源于stack exchange,提问作者ZZZzz
相关产品推荐
相关产品推荐

