本文以探讨当路由改变时动态改变页面标题的不同方法,展示在angular应用中如何应用全局变量及一些小细节。

动态地改变一个angular应用的标题的解决方法很多,我们来看看最容易想到的:监听路由改变成功事件,将标题的数据绑定到$rootScope中,改变$rootScope以改变标题。

JS:

    // 省略路由配置
    $routeProvider.when('/', {
        title: '首页',
        templateUrl: '/Assets/Views/Home.html',
        controller: 'HomeController'
    });

    .......

    myApp.run(['$location', '$rootScope', function($location, $rootScope) {
        // 每当路由改变成功的时候,更新标题
        $rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
            $rootScope.title = current.$route.title;
        });
    }]);

HTML:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <title ng-bind="title + '__网站名称'">默认标题</title>
    <!-- title 或者 $root.title都可以,因为$scope.$root = $rootScope -->
...

使用ng-bind而不使用{{ }}是为了防止title的数据没有准备好时"{{}}"会显示出来。 使用$rootScope来bind页面中的某些东西的确很方便,但是把$rootScope当成一般scope来用以及当成全局变量来用都不是个好习惯 - $rootScope存在的意义是为了创造子scope - 把它当成全局变量的容器,和在传统的js应用中使用非常多的全局变量的危害是一样的 - 对于高度模块化的angular应用来说,把一些东西放到rootScope中语义性太差,就是inject的时候你不知道它是干嘛的。

改进:

 <html ng-app="myApp" ng-controller="topCtrl">
 <head>
    <title ng-bind="title + '__网站名称'">默认标题</title>

    app.controller('topCtrl',['$scope',function($scope) {
        $scope.$on('$routeChangeSuccess', function (event, current, previous) {
            $scope.title = current.$route.title;
        });
    }]);

更简单的方式:

 <html ng-app="myApp" ng-controller="topCtrl">
 <head>
    <title>默认标题</title>
    // 省略路由配置
    $routeProvider.when('/', {
        title: '首页',
        templateUrl: '/Assets/Views/Home.html',
        controller: 'HomeController'
    });

    .......

    app.controller('topCtrl',['$scope','$window',function($scope,$window) {
        $scope.$on('$routeChangeSuccess', function (event, current, previous) {
            $window.document.title = current.$route.title;
        });
    }]);

在ui-router中如何和实现?

ui-router中的每一个state提供了可以自定义数据的data属性:

    // 省略路由配置
    $stateProvider
      .state('home', {
        url: '/',
        templateUrl: '/app/home/home.html',
        controller:'homeCtrl',
        data:{
          title:'首页',
          backgroundColor:'#efefef',
          coverImage:'....'
        }
      })

    app.controller('topCtrl',['$scope','$window',function($scope,$window) {
        $scope.$on('$stateChangeSuccess',function(evt, toState, toParams, fromState, fromParams){
            // 改变 页面的标题
            $window.document.title = (toState.data.title||'')+'——Eisneim的博客';
        })
    }]);

其他方法?

或许你还想到了做一个改变标题的service或者directive,但是都没有上述方法简便:service提供一个getTitle和setTitle方法,每次要改变title的时候调用setTitle('标题')。 directive的方式:(以下代码是我认为的解决办法,没有实际测试过)

<dynamic-title>
app.directive('dynamicTitle',function(){
    return {
        restrict:'E',
        replace:true,
        template:'<title>{{title}}</title>',
        controller:function($scope){
            $scope.$on('$routeChangeSuccess', function (event, current, previous) {
            $scope.title = current.$route.title;
        });
        }
    }
    })
    NPM和Bower的版本指定方法和含义CentOS 修复一键安装l2tpd+pptpd遇到的问题