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

如何在Angular UI-Router中避免重复配置Header和Footer

解决Angular UI-Router重复配置Header/Footer的问题

问题背景

现有Angular UI-Router代码中,每个路由状态都重复引入了Header和Footer视图配置,希望通过抽象或复用的方式避免重复,技术栈为Node.js、Webpack、Angular UI-Router。

原代码如下:

var headerView = { templateUrl: 'views/header/header.html', controller: 'HeaderCtrl' };
var footerView = { templateUrl: 'views/footer/footer.html' };
var myApp = angular.module('myApp', ['ui.router']);
myApp.controller('MainCtrl', function($scope) {});
myApp.config(function($stateProvider, $urlRouterProvider) {
  // default route
  $urlRouterProvider.otherwise("/");
  // ui router states
  $stateProvider
    .state('first', {
      url: "/first",
      views: {
        header: headerView,
        content: { template: '<p>First content</p>', controller: function($scope) {} },
        footer: footerView
      }
    })
    .state('second', {
      url: "/second",
      views: {
        header: headerView,
        content: { template: '<p>Second content</p>', controller: function($scope) {} },
        footer: footerView
      }
    });
});

解决方案

方案一:使用抽象状态(Abstract State,推荐)

这是UI-Router里处理通用视图复用最优雅的方式,抽象状态不能直接被激活,但所有子状态会自动继承它的视图、参数等配置,刚好适合把Header和Footer这类全局通用视图抽离出来:

var headerView = { templateUrl: 'views/header/header.html', controller: 'HeaderCtrl' };
var footerView = { templateUrl: 'views/footer/footer.html' };
var myApp = angular.module('myApp', ['ui.router']);

myApp.controller('MainCtrl', function($scope) {});

myApp.config(function($stateProvider, $urlRouterProvider) {
  // 默认路由
  $urlRouterProvider.otherwise("/first");

  // 定义抽象父状态,包含全局Header和Footer
  $stateProvider
    .state('app', {
      abstract: true, // 标记为抽象状态
      views: {
        header: headerView,
        footer: footerView
      }
    })
    // 子状态继承app的视图配置,只需定义content部分
    .state('app.first', {
      url: "/first",
      views: {
        'content@': { template: '<p>First content</p>', controller: function($scope) {} }
      }
    })
    .state('app.second', {
      url: "/second",
      views: {
        'content@': { template: '<p>Second content</p>', controller: function($scope) {} }
      }
    });
});

小提示:

  • 子状态的视图名称'content@'里的@,表示直接渲染到根模板(也就是index.html里的<div ui-view="content"></div>),如果不加,会默认在父状态的视图中查找对应的ui-view,这里我们需要直接用根视图的content区域,所以加上@。
  • 抽象状态还能复用全局resolve、路由参数、自定义数据等,扩展性拉满。

方案二:封装通用视图配置对象

如果暂时不想用抽象状态,也可以把通用视图封装成一个可复用的对象,然后在每个状态中合并配置:

var headerView = { templateUrl: 'views/header/header.html', controller: 'HeaderCtrl' };
var footerView = { templateUrl: 'views/footer/footer.html' };
// 封装通用视图基础配置
var baseViews = {
  header: headerView,
  footer: footerView
};

var myApp = angular.module('myApp', ['ui.router']);

myApp.controller('MainCtrl', function($scope) {});

myApp.config(function($stateProvider, $urlRouterProvider) {
  $urlRouterProvider.otherwise("/first");

  $stateProvider
    .state('first', {
      url: "/first",
      // 合并基础视图和当前状态的content视图
      views: Object.assign({}, baseViews, {
        content: { template: '<p>First content</p>', controller: function($scope) {} }
      })
    })
    .state('second', {
      url: "/second",
      views: Object.assign({}, baseViews, {
        content: { template: '<p>Second content</p>', controller: function($scope) {} }
      })
    });
});

小提示:

  • 用Object.assign合并基础视图和自定义视图,避免重复编写header和footer配置;如果项目里用了Lodash,也可以用_.merge实现更深度的合并。

内容的提问来源于stack exchange,提问作者D V Yogesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:03:21