本文以探讨当路由改变时动态改变页面标题的不同方法,展示在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;
});
}
}
})