AngularJS+ui-router实现非addin路由懒加载指定JS/CSS文件
解决AngularJS+ui-router下按路由按需加载资源的问题
嘿,这个需求我之前也碰到过,用ocLazyLoad结合ui-router的特性就能完美搞定,给你两种实用的实现方式:
方法一:全局路由Resolve(推荐)
这种方式更优雅,把资源加载逻辑统一注入到所有路由的解析流程中,不用每个路由单独配置:
首先,在你的app配置里,通过$stateProvider.decorator给所有路由添加全局的resolve逻辑,自动判断当前路由是否属于/addin/开头的路径,仅在非addin路由下加载额外资源:
angular.module('yourApp', ['ui.router', 'oc.lazyLoad']) .config(function($stateProvider, $urlRouterProvider) { // 给所有路由统一添加资源加载的resolve $stateProvider.decorator('resolve', function(state, parent) { const originalResolve = parent(state); // 加入按需加载逻辑 originalResolve.loadExtraResources = function($ocLazyLoad, $state) { // 判断当前路由是否以/addin/开头,兼容旧浏览器可以换成indexOf('/addin/') === 0 const isAddinRoute = $state.current.url.startsWith('/addin/'); if (!isAddinRoute) { // 加载需要的额外JS/CSS,数组支持多个资源 return $ocLazyLoad.load([ 'path/to/your/extra-script.js', 'path/to/your/extra-style.css', 'path/to/another-script.js' ]); } // 如果是addin路由,直接返回已resolved的Promise,不加载资源 return Promise.resolve(); }; return originalResolve; }); // 正常配置你的路由结构 $stateProvider .state('addin.detail', { url: '/addin/:detailId', templateUrl: 'views/addin-detail.html', controller: 'AddinDetailCtrl' }) .state('dashboard', { url: '/dashboard', templateUrl: 'views/dashboard.html', controller: 'DashboardCtrl' }) .state('settings', { url: '/settings', templateUrl: 'views/settings.html', controller: 'SettingsCtrl' }); $urlRouterProvider.otherwise('/dashboard'); });
方法二:监听路由变化事件
如果不想用resolve,也可以在app的run块里监听路由启动事件,动态判断并加载资源:
angular.module('yourApp') .run(function($rootScope, $ocLazyLoad) { // 针对旧版ui-router(0.4.x及以下)用$stateChangeStart事件 $rootScope.$on('$stateChangeStart', function(event, toState) { // 判断目标路由是否为addin开头 const isAddinRoute = toState.url.startsWith('/addin/'); if (!isAddinRoute) { // 加载额外资源,*ocLazyLoad会自动缓存已加载的资源*,不用担心重复加载 $ocLazyLoad.load([ 'path/to/your/extra-script.js', 'path/to/your/extra-style.css' ]); } }); // 如果是ui-router 1.x及以上版本,更推荐用$transitions服务 // $transitions.onStart({}, function(trans) { // const toState = trans.to(); // const isAddinRoute = toState.url.startsWith('/addin/'); // if (!isAddinRoute) { // return $ocLazyLoad.load([ // 'path/to/your/extra-script.js', // 'path/to/your/extra-style.css' // ]); // } // }); });
几个关键注意点
- 确保已经把
oc.lazyLoad作为依赖注入到你的AngularJS模块中,并且正确引入了ocLazyLoad的脚本文件。 - 如果需要兼容ES5以下的旧浏览器,把
startsWith('/addin/')替换成indexOf('/addin/') === 0,判断逻辑是一样的。 - ocLazyLoad默认会缓存已加载的资源,所以多次进入非addin路由时不会重复加载,不会造成性能浪费。
- 不管是嵌套路由还是平级路由,只要路由的url以
/addin/开头,都会被正确识别,不会加载额外资源。
内容的提问来源于stack exchange,提问作者SoftTimur
相关产品推荐
相关产品推荐

