You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:17:57