AngularJS控制器能否延迟加载?加载时遇ctrl未找到错误
AngularJS控制器延迟加载方案(解决'ctrl is not found'错误)
当然可以延迟加载AngularJS控制器啦!你碰到的「ctrl is not found」问题,本质是AngularJS在初始化阶段没找到对应控制器的注册信息——毕竟你延迟加载的控制器是在Angular启动之后才加载的,默认的注册方式已经不生效了,得换个思路来搞。
下面是我常用的实现步骤,亲测有效:
1. 提前保存$controllerProvider引用
AngularJS启动完成后,就没法直接用angular.module().controller()注册新控制器了,所以得在模块配置阶段先把$controllerProvider存起来,后面用它注册延迟加载的控制器:
var myApp = angular.module('myApp', []); // 全局保存$controllerProvider引用 let controllerProvider; myApp.config(['$controllerProvider', function($ctrlProvider) { controllerProvider = $ctrlProvider; }]);
2. 写一个动态加载控制器的工具函数
我们需要一个方法来异步加载控制器的脚本文件,加载完成后用刚才保存的controllerProvider注册控制器:
function loadLazyController(ctrlName, ctrlUrl) { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = ctrlUrl; script.onload = () => { // 假设控制器脚本里把控制器函数挂在了window上 controllerProvider.register(ctrlName, window[ctrlName]); resolve(); }; script.onerror = () => reject(new Error(`加载控制器${ctrlName}失败`)); document.body.appendChild(script); }); }
3. 在需要的地方触发延迟加载
比如结合路由(ui-router或者ngRoute),在进入对应路由前加载控制器,确保Angular实例化控制器前已经完成注册:
用ui-router的例子:
myApp.config(['$stateProvider', function($stateProvider) { $stateProvider.state('lazyPage', { url: '/lazy', templateUrl: 'lazy-page.html', resolve: { // 路由跳转前先加载控制器 loadController: () => loadLazyController('LazyCtrl', '/js/lazy-controller.js') }, controller: 'LazyCtrl' }); }]);
4. 控制器脚本的写法
你的延迟加载控制器脚本可以这么写,把控制器函数暴露到window上(或者直接在脚本里用controllerProvider注册):
// /js/lazy-controller.js function LazyCtrl($scope) { $scope.greeting = '这是延迟加载的控制器!'; }
或者更严谨一点,直接在脚本里用我们保存的provider注册(避免污染全局变量):
// /js/lazy-controller.js angular.module('myApp').run(['$controllerProvider', function($ctrlProvider) { $ctrlProvider.register('LazyCtrl', function($scope) { $scope.greeting = '这是延迟加载的控制器!'; }); }]);
常见坑点提醒
- 一定要确保控制器注册完成后,Angular才去实例化它(比如路由的resolve就是干这个的),不然还是会报找不到控制器的错误。
- 不要用
angular.module('myApp').controller()来注册延迟加载的控制器,模块初始化后这个方法就失效了,必须用我们提前保存的controllerProvider。
内容的提问来源于stack exchange,提问作者TatiOverflow
相关产品推荐
相关产品推荐

