简体   繁体   English

用angularjs改变身体背景颜色

[英]Changing body background color with angularjs

I want to be able to change the background color of <body> depending on what the current path is. 我希望能够根据当前路径更改<body>的背景颜色。

I tried doing it by checking $location.path() whenever the path was changed and then using the ng-style directive to change the background color but this seems like a hack (and didn't work). 我尝试通过检查$ location.path()每当路径被更改然后使用ng-style指令来更改背景颜色,但这似乎是一个黑客(并没有工作)。

What would be a more decoupled way to achieve this? 实现这一目标的解耦方式是什么?

Here's the code I wrote if anyone wants to see it. 这是我写的代码,如果有人想看到它。

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'};
    }

  });
}]);

To decouple such a dynamic change in style, data, content and etc., it is often practical to create another angular module that contains an interface(Custom Provider) that can give you access to these changes before and after the configuration level. 要在样式,数据,内容等中分离这种动态变化,通常可以创建另一个包含接口(自定义提供程序)的角度模块,该接口可以让您在配置级别之前和之后访问这些更改。 Here is a plunker to provide a view of what I'll be discussing below. 这是一个提供我将在下面讨论的内容的插图

For this answer, I have created a small module(route-data.js) with a provider , RouteData, which exposes two function configurations: 对于这个答案,我创建了一个带有provider RouteData的小模块(route-data.js),它provider两个函数配置:

applyConfig() - assigns settings to be accessed in the RouteData service. applyConfig() - 指定要在RouteData服务中访问的设置。 hookToRootScope() - hooks the RouteData service in the $rootScope hence making it available to all child scopes to be created and the entire application. hookToRootScope() - 在$rootScope挂钩RouteData服务,从而使其可供所有要创建的子作用域和整个应用程序使用。

The RouteData provider has a RouteData() service that provides access to methods which sets and gets RouteData settings that will be provided in the $routeProvider configuration. RouteData提供程序具有RouteData()服务,该服务提供对设置和获取将在$routeProvider配置中提供的RouteData设置的方法的访问。

(If you're not familiar with providers and services, read more about it here ) (如果您不熟悉提供商和服务,请在此处阅读更多相关信息)

(If you're not familiar with the config() and run() methods, you can read more in here ) (如果您不熟悉config()run()方法,可以在这里阅读更多内容)

route-data.js 路由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]);
    } 
  });
}]);

The script below shows how to use the RouteData Module above via injecting the RouteDataProvider in the configuration level and apply default configurations such as the bodyStyle via RouteDataProvider.applyConfig() , you may also add more settings before the application is fully running. 下面的脚本显示了如何通过在配置级别注入RouteDataProvider并通过RouteDataProvider.applyConfig()应用默认配置(如bodyStyle RouteDataProvider.applyConfig()来使用上面的RouteData模块,您还可以在应用程序完全运行之前添加更多设置。 Hook it up in the $rootScope by setting RouteDataProvider.hookToRootScope() to true. 通过将RouteDataProvider.hookToRootScope()设置为true,将其连接到$ rootScope中。 Lastly, appending data, RouteData eg 最后,附加数据,例如RouteData

RouteData: {
      bodyStyle: {
        'background-color': 'green'
      }
    }

to be sent in by the $routeProvider and processed by the run() method defined in the RouteData module which initializes the settings for the RouteData services to be accessed in the application. 由$ routeProvider发送并由RouteData模块中定义的run()方法处理,该方法初始化要在应用程序中访问的RouteData服务的设置。

script.js 的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) {

}]);

So the final piece of code to be added in your index page or any other page would be something like this. 因此,要在索引页面或任何其他页面中添加的最后一段代码将是这样的。

A portion of index.html index.html的一部分

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

One way to style the body is to add ng-view as a body attribute, then use ng-class or ng-style (I did not use any other option to date). 设置主体样式的一种方法是将ng-view添加为body属性,然后使用ng-classng-style (我没有使用任何其他选项来约会)。

For example: 例如:

<!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>

In this example, the login class is applied to the body only when loginBody is a true value in the current scope, set in a login controller. 在此示例中,仅当loginBody是当前作用域中的true值(在登录控制器中设置)时, loginBodylogin类应用于正文。

This is much less flexible than the approach offered by @ryeballar. 这比@ryeballar提供的方法灵活得多。 It may just be enough in some cases. 在某些情况下,这可能就足够了。

I noticed that when I navigate to another page without page reload background color still remains, so I am doing this (I am using angular ui-router ): 我注意到当我导航到没有页面重新加载的另一页时,背景颜色仍然存在,所以我这样做(我使用的是角度ui-router ):

In config: 在配置中:

$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';
            }
        });

In the Template 在模板中

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

In CSS: 在CSS中:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM