首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在AngularJS中包含视图/局部特定样式

如何在AngularJS中包含视图/局部特定样式
EN

Stack Overflow用户
提问于 2013-03-04 10:09:07
回答 7查看 103K关注 0票数 132

对于我的应用程序使用的各种视图,使用单独的样式表的正确/可接受的方式是什么?

目前,我在view/partial的html顶部放置了一个link元素,但有人告诉我这是一种糟糕的做法,尽管所有现代浏览器都支持它,但我明白为什么它不受欢迎。

另一种可能是将单独的样式表放在index.html的head中,但我希望它只在以performance的名义加载视图时才加载样式表。

这是不是不好的做法,因为样式只有在css从服务器加载后才会生效,从而导致在运行速度较慢的浏览器中快速闪现未格式化的内容?虽然我正在本地测试,但我还没有看到这一点。

有没有办法通过传递给Angular的$routeProvider.when的对象来加载CSS

提前感谢!

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2013-12-05 23:54:06

我知道这个问题现在已经过时了,但在对这个问题的各种解决方案进行了大量研究后,我想我可能已经想出了一个更好的解决方案。

更新1:自从发布这个答案以来,我已经将所有这些代码添加到了我发布到GitHub的一个简单服务中。存储库位于here。请随时查看它以获取更多信息。

更新2:如果您所需要的只是为您的路线引入样式表的轻量级解决方案,那么这个答案非常棒。如果您想要一个更完整的解决方案来管理整个应用程序中的按需样式表,那么您可能需要查看Door3's AngularCSS project。它提供了更细粒度的功能。

如果将来有人对此感兴趣,这里是我想出来的:

1.为 <head> 元素创建自定义指令:

代码语言:javascript
复制
app.directive('head', ['$rootScope','$compile',
    function($rootScope, $compile){
        return {
            restrict: 'E',
            link: function(scope, elem){
                var html = '<link rel="stylesheet" ng-repeat="(routeCtrl, cssUrl) in routeStyles" ng-href="{{cssUrl}}" />';
                elem.append($compile(html)(scope));
                scope.routeStyles = {};
                $rootScope.$on('$routeChangeStart', function (e, next, current) {
                    if(current && current.$$route && current.$$route.css){
                        if(!angular.isArray(current.$$route.css)){
                            current.$$route.css = [current.$$route.css];
                        }
                        angular.forEach(current.$$route.css, function(sheet){
                            delete scope.routeStyles[sheet];
                        });
                    }
                    if(next && next.$$route && next.$$route.css){
                        if(!angular.isArray(next.$$route.css)){
                            next.$$route.css = [next.$$route.css];
                        }
                        angular.forEach(next.$$route.css, function(sheet){
                            scope.routeStyles[sheet] = sheet;
                        });
                    }
                });
            }
        };
    }
]);

此指令执行以下操作:

ng-href.

  • It使用<link />编译(使用$compile)一个html字符串,该字符串使用scope.routeStylesscope.routeStyles对象中的每个项目创建一组<link />标记,并将编译后的这组<link />元素附加到<head>标记。

  • 然后使用$rootScope侦听'$routeChangeStart'事件。对于每个'$routeChangeStart'事件,它都会获取“当前”$$route对象(用户将要离开的路由),并从<head>标记中删除其特定于部分的css文件。它还获取“下一个”$$route对象(用户将要转到的路径),并将其任何特定于部分的css文件添加到<head>标记。

  • 和compiled <link />标记的ng-repeat部分根据添加到scope.routeStyles对象或从中删除的内容来处理所有特定于页面的样式表的添加和删除。

注意:这要求您的ng-app属性在<html>元素上,而不是在<body><html>__内的任何地方。

2.使用 $routeProvider**:**指定哪些样式表属于哪些路由

代码语言:javascript
复制
app.config(['$routeProvider', function($routeProvider){
    $routeProvider
        .when('/some/route/1', {
            templateUrl: 'partials/partial1.html', 
            controller: 'Partial1Ctrl',
            css: 'css/partial1.css'
        })
        .when('/some/route/2', {
            templateUrl: 'partials/partial2.html',
            controller: 'Partial2Ctrl'
        })
        .when('/some/route/3', {
            templateUrl: 'partials/partial3.html',
            controller: 'Partial3Ctrl',
            css: ['css/partial3_1.css','css/partial3_2.css']
        })
}]);

此配置将一个自定义css属性添加到用于设置每个页面的路由的对象。该对象作为.$$route传递给每个'$routeChangeStart'事件。因此,在侦听'$routeChangeStart'事件时,我们可以获取指定的css属性,并根据需要添加/删除这些<link />标记。请注意,在路由上指定css属性是完全可选的,因为在'/some/route/2'示例中省略了该属性。如果路由没有css属性,则<head>指令将不会对该路由执行任何操作。还要注意,您甚至可以为每个路由提供多个特定于页面的样式表,如上面的'/some/route/3'示例所示,其中css属性是该路由所需样式表的相对路径数组。

3.你已经完成了这两件事,设置了所有需要的东西,在我看来,它用最干净的代码做到了这一点。

希望这对其他和我一样在这个问题上苦苦挣扎的人有所帮助。

票数 150
EN

Stack Overflow用户

发布于 2015-01-14 02:17:06

@tennisgent的解决方案很棒。然而,我认为这是有一点限制的。

Angular中的模块化和封装超越了路由。基于web正在走向基于组件的开发的方式,在指令中应用这一点也很重要。

正如您已经知道的,在Angular中,我们可以在页面和组件中包含模板(结构)和控制器(行为)。AngularCSS实现了最后一个缺失的部分:附加样式表(表示)。

对于完整的解决方案,我建议使用AngularCSS。

  1. 支持Angular的ngRoute、UI路由器、指令、控制器和服务。
  2. 不需要在<html>标记中包含ng-app。当您在同一页面上运行多个应用程序时,这一点非常重要。您可以自定义样式表的注入位置: head、body、自定义选择器、etc...
  3. Supports预加载、持久化和缓存busting
  4. Supports媒体查询,并通过matchMedia

优化页面加载

https://github.com/door3/angular-css

下面是一些示例:

路由

代码语言:javascript
复制
  $routeProvider
    .when('/page1', {
      templateUrl: 'page1/page1.html',
      controller: 'page1Ctrl',
      /* Now you can bind css to routes */
      css: 'page1/page1.css'
    })
    .when('/page2', {
      templateUrl: 'page2/page2.html',
      controller: 'page2Ctrl',
      /* You can also enable features like bust cache, persist and preload */
      css: {
        href: 'page2/page2.css',
        bustCache: true
      }
    })
    .when('/page3', {
      templateUrl: 'page3/page3.html',
      controller: 'page3Ctrl',
      /* This is how you can include multiple stylesheets */
      css: ['page3/page3.css','page3/page3-2.css']
    })
    .when('/page4', {
      templateUrl: 'page4/page4.html',
      controller: 'page4Ctrl',
      css: [
        {
          href: 'page4/page4.css',
          persist: true
        }, {
          href: 'page4/page4.mobile.css',
          /* Media Query support via window.matchMedia API
           * This will only add the stylesheet if the breakpoint matches */
          media: 'screen and (max-width : 768px)'
        }, {
          href: 'page4/page4.print.css',
          media: 'print'
        }
      ]
    });

指令

代码语言:javascript
复制
myApp.directive('myDirective', function () {
  return {
    restrict: 'E',
    templateUrl: 'my-directive/my-directive.html',
    css: 'my-directive/my-directive.css'
  }
});

此外,您可以在边缘情况下使用$css服务:

代码语言:javascript
复制
myApp.controller('pageCtrl', function ($scope, $css) {

  // Binds stylesheet(s) to scope create/destroy events (recommended over add/remove)
  $css.bind({ 
    href: 'my-page/my-page.css'
  }, $scope);

  // Simply add stylesheet(s)
  $css.add('my-page/my-page.css');

  // Simply remove stylesheet(s)
  $css.remove(['my-page/my-page.css','my-page/my-page2.css']);

  // Remove all stylesheets
  $css.removeAll();

});

你可以在这里阅读更多关于AngularCSS的内容:

http://door3.com/insights/introducing-angularcss-css-demand-angularjs

票数 34
EN

Stack Overflow用户

发布于 2013-03-04 10:38:12

可以将新的样式表附加到$routeProvider中的head。为了简单起见,我使用了字符串,但也可以创建新的link元素,或者为样式表创建一个服务

代码语言:javascript
复制
/* check if already exists first - note ID used on link element*/
/* could also track within scope object*/
if( !angular.element('link#myViewName').length){
    angular.element('head').append('<link id="myViewName" href="myViewName.css" rel="stylesheet">');
}

在页面中预加载的最大好处是任何背景图像都将已经存在,并且不那么活泼的FOUC

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15193492

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档