如何在单个Angular UI Router路由中加载多模板与控制器?
嗨,我完全懂你现在的困扰——好久没碰Angular,想把模板和控制器拆分成单独文件,又希望在同一路由的页面里全部展示,结果用UI Router试了半天只能加载第一个,这其实是UI Router的多视图特性没用到位,给你几个实用的解决方案:
views配置(最推荐,原生支持多视图) UI Router本身就设计了在单一路由下加载多个独立视图的能力,每个视图可以对应自己的模板和控制器,完美匹配你拆分文件的需求。
举个实际的配置例子,假设你的页面需要三个独立区块:头部、主内容、侧边栏,每个都有自己的模板和控制器:
angular.module('yourApp') .config(function($stateProvider) { $stateProvider.state('home', { url: '/home', // 这里的views对象就是用来定义多个视图的 views: { // 格式:'视图名称@根模板',@表示相对于index.html的根视图 'header@': { templateUrl: 'templates/header.html', controller: 'HeaderController' }, 'mainContent@': { templateUrl: 'templates/main-content.html', controller: 'MainContentController' }, 'sidebar@': { templateUrl: 'templates/sidebar.html', controller: 'SidebarController' } } }); });
然后在你的根页面(比如index.html)里,给每个视图预留对应的挂载位置:
<!-- 头部视图的挂载点 --> <div ui-view="header"></div> <div class="page-container"> <!-- 主内容视图的挂载点 --> <div ui-view="mainContent"></div> <!-- 侧边栏视图的挂载点 --> <div ui-view="sidebar"></div> </div>
这样当你访问/home路由时,三个视图会同时加载各自的模板和控制器,完全实现文件拆分但同页面展示的效果。
ng-include配合控制器(适合简单场景) 如果你的项目场景比较简单,不想折腾复杂的路由配置,也可以用ng-include在主模板里加载子模板,再通过ng-controller绑定对应的控制器。
比如先写一个主模板home.html:
<div ng-controller="HomeMainController"> <!-- 加载头部模板并绑定控制器 --> <ng-include src="'templates/header.html'" ng-controller="HeaderController"></ng-include> <!-- 加载主内容模板并绑定控制器 --> <ng-include src="'templates/main-content.html'" ng-controller="MainContentController"></ng-include> <!-- 加载侧边栏模板并绑定控制器 --> <ng-include src="'templates/sidebar.html'" ng-controller="SidebarController"></ng-include> </div>
然后路由只需要指向这个主模板:
$stateProvider.state('home', { url: '/home', templateUrl: 'templates/home.html', controller: 'HomeMainController' });
不过要注意,子模板的控制器会继承主控制器的作用域,复杂场景下可能会有作用域冲突,所以这种方法更适合简单的页面拆分。
如果你的Angular版本在1.5及以上,更推荐用组件化的方式拆分——把每个区块做成独立的组件,封装自己的模板和控制器,然后在主页面里引用组件标签即可。
比如定义一个头部组件:
angular.module('yourApp') .component('appHeader', { templateUrl: 'templates/header.html', controller: 'HeaderController' });
同理定义appMainContent和appSidebar组件,然后在主模板home.html里直接引用:
<app-header></app-header> <div class="page-container"> <app-main-content></app-main-content> <app-sidebar></app-sidebar> </div>
路由配置还是指向主模板,这样每个组件都是独立的文件,代码复用性和可维护性更高,也是Angular向新版本过渡的最佳实践。
最后提醒一句:不管用哪种方法,都要确保所有的控制器、模板文件已经正确引入到项目中(如果是大型项目,推荐用Webpack、RequireJS这类模块加载器来管理文件依赖),不然会出现加载失败的情况哦。
内容的提问来源于stack exchange,提问作者amacdonald

