使用angularjs更改页面背景颜色

6
我想能够根据当前路径更改<body>的背景颜色。
我尝试通过在路径改变时检查$location.path(),然后使用ng-style指令更改背景颜色,但这似乎是一种hack方法(并且没有起作用)。
有什么更加解耦的方法可以实现这一点?
以下是我编写的代码,如果有人想查看的话。
app.controller('backgroundCtrl', ['$rootScope', '$scope', '$route', '$location', function($rootScope, $scope, $route, $location){
  $rootScope.$on('$routeChangeStart', function(){

    if ($location.path() == '/'){
      $scope.backgroundStyle = {background: '#ffffff'};
    } else {
      $scope.backgroundStyle = {background: '#000000'};
    }

  });
}]);
3个回答

12
为了解耦样式、数据、内容等的动态变化,通常需要创建另一个 Angular 模块,其中包含一个接口(自定义提供者),该接口可以让您在配置级别之前和之后访问这些更改。这里有一个 plunker,以便提供下面将要讨论的内容。
对于这个答案,我创建了一个小模块(route-data.js),其中包含一个提供者(RouteData),它公开了两个函数配置: applyConfig() - 分配要在 RouteData 服务中访问的设置。 hookToRootScope() - 将 RouteData 服务挂钩在 $rootScope 中,从而使其可用于将要创建的所有子作用域和整个应用程序。
RouteData 提供程序具有一个 RouteData() 服务,该服务提供了访问方法,用于设置和获取将在 $routeProvider 配置中提供的 RouteData 设置。
(如果您不熟悉提供者和服务,请在here阅读更多信息)

如果您不熟悉config()run()方法,可以在这里阅读更多信息。

route-data.js

angular.module('RouteData', []).

provider('RouteData', function () {
  var settings = {};
  var hookToRootScope = false;

  this.applyConfig = function(newSettings) {
    settings = newSettings;
  };

  this.hookToRootScope = function(enableRootScopeHook) {
    hookToRootScope = enableRootScopeHook;
  };

  function RouteData() {

    this.set = function(index, value) {
      settings[index] = value;
    };

    this.get = function(index) {
      if(settings.hasOwnProperty(index)) {
        return settings[index];
      } else {
        console.log('RouteData: Attempt to access a propery that has not been set');
      }
    };

    this.isHookedToRootSope = function() {
      return hookToRootScope;
    };
  }

  this.$get = function() {
      return new RouteData();
  };
}).

run(['$location', '$rootScope', 'RouteData', function($location, $rootScope, RouteData) {
  if(RouteData.isHookedToRootSope()) {
    $rootScope.RouteData = RouteData;
  }

  $rootScope.$on('$routeChangeStart', function(event, current, previous) {
    var route = current.$$route;
    if(typeof(route) !== 'undefined' && typeof(route['RouteData']) !== 'undefined') {
      var data = route['RouteData'];
      for(var index in data)
        RouteData.set(index, data[index]);
    } 
  });
}]);

以下脚本展示了如何通过在配置级别注入RouteDataProvider来使用上述的RouteData模块,并应用默认配置,例如通过RouteDataProvider.applyConfig()设置bodyStyle。在应用程序完全运行之前,您还可以添加更多设置。通过将RouteDataProvider.hookToRootScope()设置为true,在$rootScope中连接它。最后,附加数据,例如RouteData。
RouteData: {
      bodyStyle: {
        'background-color': 'green'
      }
    }

由$routeProvider发送并由RouteData模块中定义的run()方法处理,该方法初始化RouteData服务的设置以便在应用程序中访问。

script.js

angular.module('app', ['ngRoute', 'RouteData']).

config(['$routeProvider', 'RouteDataProvider', function($routeProvider, RouteDataProvider) {
  RouteDataProvider.applyConfig({
    bodyStyle: {
      'background-color': 'white'
    }
  });

  RouteDataProvider.hookToRootScope(true);

  $routeProvider.when('/landing', {
    RouteData: {
      bodyStyle: {
        'background-color': 'green'
      }
    },
    templateUrl: 'landing.html',
    controller: 'LandingController'  
  }).when('/login', {
    RouteData: {
     bodyStyle: {
         'background-color': 'gray',
         padding: '10px',
         border: '5px solid black',
         'border-radius': '1px solid black'
     }
    },
    templateUrl: 'login.html',
    controller: 'LoginController'
  }).otherwise({
    redirectTo: '/landing'
  });

}]).

controller('LoginController', ['$scope', function($scope) {

}]).

controller('LandingController', ['$scope', function($scope) {

}]);

因此,最终需要添加到您的主页或任何其他页面的代码将类似于以下内容。

index.html 的一部分

<body ng-style="RouteData.get('bodyStyle')"> 
    <a href="#/landing">Landing</a> | 
    <a href="#/login">Login</a>
    <div ng-view></div>
</body>

非常感谢您提供这么详细的答案,我很感激。 - user1215653
有一个打字错误导致了程序崩溃。应该是this.hookToRootScope而不是this.hookeToRootScope。 - MalcolmInTheCenter

4

一种样式化 body 的方法是将 ng-view 添加为 body 属性,然后使用 ng-classng-style(我目前没有使用其他选项)。

例如:

<!doctype html>
<html ng-app="my-app">
  <head>
    <title>My Site</title>
    <script src="angular/angular.js"></script>
  </head>
  <body ng-class="{login:loginBody}" ng-view>
    <script src="my-app.js"></script>
  </body>
</html>

在这个例子中,只有在当前作用域中loginBody是真值(由登录控制器设置)时,才会将login类应用于元素。这种方法比@ryeballar提供的方法灵活性要小得多,但在某些情况下可能已经足够了。

0
我注意到当我在不刷新页面的情况下导航到另一个页面时,背景颜色仍然保持不变,所以我正在做这个(我正在使用angular ui-router): 在配置中:
$stateProvider.state('app.login',{
            url: '/login',
            onExit: function($rootScope){
                $rootScope.bodyClass = 'body-one';
            },
           templateUrl: 'ng/templates/auth/login-page-one.html',
            controller: function($rootScope){
                $rootScope.bodyClass = 'body-two';
            }
        })

        .state('app.signup',{
            url: '/signup',
            onExit: function($rootScope){
                $rootScope.bodyClass = 'body-one';
            },
            templateUrl: 'ng/templates/auth/signup-page-one.html',
            controller: function($rootScope){
                $rootScope.bodyClass = 'body-two';
            }
        });

在模板中

<body class="{{bodyClass ? bodyClass : 'body-one'}}">

CSS中:

.body-one{
    margin-top: 50px;
    background: #f0f4fb;
}

.body-two{
    margin: 0;
    padding: 0;
    background: #2e9fff;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接