什么是使用单独的样式表对我的应用程序使用的各种观点的正确/接受的方式?
目前我把链接元素在顶部视图/分的HTML,但我已经告诉他们这是不好的做法,即使所有现代浏览器都支持它,但我能看到为什么它皱眉。
另一种可能性是将单独的样式表在我的index.html的head
,但我想,如果它认为是在性能的名字被载入其只加载样式表。
这是不好的做法,因为造型将不会生效后的CSS加载形成服务器,导致未格式化的内容快速闪过一个缓慢的浏览器,直到? 我还没有看到这个,虽然我在本地测试它。
有没有一种方式来加载通过传递到角的物体的CSS $routeProvider.when
?
提前致谢!
Answer 1:
我知道这个问题是老了,但这样做一吨的各种解决方案研究这个问题后,我想我可能会拿出一个更好的解决方案。
更新1:由于张贴这个答案,我加入了所有这些代码来,我已经发布到GitHub的一个简单的服务。 回购位于这里 。 随时检查出来的更多信息。
更新2:这个答案是伟大的,如果你需要的是在样式表拉你的路由的轻量级解决方案。 如果您想为整个应用程序管理的按需样式更完整的解决方案,您可能希望签DOOR3的AngularCSS项目 。 它提供了更精细的功能。
在未来的情况下,任何人有兴趣,这里就是我想出了:
1.创建自定义指令<head>
元素:
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;
});
}
});
}
};
}
]);
该指令做以下几件事:
- 它编译(使用
$compile
)创建一组HTML字符串<link />
标签中的每一个项目scope.routeStyles
使用对象ng-repeat
和ng-href
。 - 其附加的是编译的集合
<link />
元素到<head>
标记。 - 然后,它使用
$rootScope
监听'$routeChangeStart'
事件。 对于每一个'$routeChangeStart'
事件,它抓住“当前” $$route
对象(即,用户将要离开的路线),并从除去其部分特定的CSS文件(S) <head>
标记。 它还抓住“下一个” $$route
对象(该用户是约去路线),并增加了它的任何部分的特异性CSS文件(多个)到<head>
标记。 - 和
ng-repeat
编译的一部分<link />
标签处理所有的添加和基于什么被添加到或从删除特定页面的样式表中移除的scope.routeStyles
对象。
注意: 这需要你的ng-app
属性是在<html>
元素,不是<body>
或内部的任何<html>
2.指定样式表属于哪个使用路由$routeProvider
:
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
属性用来设置每一页的路线的对象。 这对象被传递给每一个'$routeChangeStart'
事件作为.$$route
。 所以听的时候'$routeChangeStart'
事件中,我们可以抓住css
,我们指定的属性和追加/删除那些<link />
根据需要标签。 请注意,指定一个css
的路线上属性完全是可选的,因为它是从省略'/some/route/2'
的例子。 如果路由没有一个css
属性,在<head>
的指令就干脆什么都不做了这条路线。 还请注意,甚至可以有多个特定页面的样式表每路线,如在'/some/route/3'
上述例子中,其中css
属性是需要该路线的样式表的相对路径的阵列。
3.大功告成 ,需要的是这两件事情建立的一切,它这样做,在我看来,用干净的代码可能。
希望可以帮助别人谁可能有这个问题,就像我很挣扎。
Answer 2:
@ tennisgent的解决方案是巨大的。 不过,我觉得是有点有限。
模块化和封装在角超越的路线。 基于Web的向着基于组件的开发移动方式,在指令适用这个也很重要。
正如你已经知道,在我们的角可以包括页面和组件模板(结构)和控制器(行为)。 AngularCSS使最后缺少的部分:将样式表(演示)。
对于一个完整的解决方案,我建议使用AngularCSS。
- 支持角的ngRoute,UI路由器,指令控制器和服务。
- 不要求有
ng-app
在<html>
标记。 这一点很重要,当你有在同一页上运行多个应用程序 - 您可以自定义样式表注入:头部,身体,自定义选择,等等。
- 支持预加载,坚持和缓存无效
- 支持媒体查询,并通过matchMedia API优化页面加载
https://github.com/door3/angular-css
这里有些例子:
路线
$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'
}
]
});
指令
myApp.directive('myDirective', function () {
return {
restrict: 'E',
templateUrl: 'my-directive/my-directive.html',
css: 'my-directive/my-directive.css'
}
});
此外,还可以使用$css
的边缘情况服务:
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
Answer 3:
可以追加一个新的样式表内前往$routeProvider
。 为简单起见我使用一个字符串,但也创造新的链接元素,或创建样式表服务
/* 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">');
}
在页面prelaoding的最大的好处是任何背景图片就已经存在,而且少lieklyhood FOUC
Answer 4:
@ SZ3,今天没带够有趣,我不得不这样做正是你所要达到:“ 加载特定的CSS文件只有当用户访问 ”的特定页面。 所以我用上面的解决方案。
但是我在这里回答你的最后一个问题:“ 究竟我应该在哪里把代码。 任何想法 ?
你是对的,包括代码到的决心 ,但你需要改变了一下格式。
看看下面的代码:
.when('/home', {
title:'Home - ' + siteName,
bodyClass: 'home',
templateUrl: function(params) {
return 'views/home.html';
},
controler: 'homeCtrl',
resolve: {
style : function(){
/* check if already exists first - note ID used on link element*/
/* could also track within scope object*/
if( !angular.element('link#mobile').length){
angular.element('head').append('<link id="home" href="home.css" rel="stylesheet">');
}
}
}
})
我刚刚测试,它的正常工作 ,它注入HTML和加载我的“home.css”只有当我打了一个“/ home”路线。
完整的解释可以发现在这里 ,但基本上解决:应在格式得到一个对象
{
'key' : string or function()
}
你能说出你喜欢的“ 密钥 ”任何事情-在我的情况下,我叫“ 风格 ”。
然后该值,你有两个选择:
如果它是一个字符串 ,那么它是一个服务的别名。
如果它的功能 ,然后将其注入和返回值被视为依赖。
这里主要的一点是,在函数内部的代码会之前控制器被实例化和$ routeChangeSuccess事件被触发之前执行。
希望帮助。
Answer 5:
太棒了,谢谢你!! 只是不得不做出一些调整,以得到它与UI的路由器工作:
var app = app || angular.module('app', []);
app.directive('head', ['$rootScope', '$compile', '$state', function ($rootScope, $compile, $state) {
return {
restrict: 'E',
link: function ($scope, elem, attrs, ctrls) {
var html = '<link rel="stylesheet" ng-repeat="(routeCtrl, cssUrl) in routeStyles" ng-href="{{cssUrl}}" />';
var el = $compile(html)($scope)
elem.append(el);
$scope.routeStyles = {};
function applyStyles(state, action) {
var sheets = state ? state.css : null;
if (state.parent) {
var parentState = $state.get(state.parent)
applyStyles(parentState, action);
}
if (sheets) {
if (!Array.isArray(sheets)) {
sheets = [sheets];
}
angular.forEach(sheets, function (sheet) {
action(sheet);
});
}
}
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
applyStyles(fromState, function(sheet) {
delete $scope.routeStyles[sheet];
console.log('>> remove >> ', sheet);
});
applyStyles(toState, function(sheet) {
$scope.routeStyles[sheet] = sheet;
console.log('>> add >> ', sheet);
});
});
}
}
}]);
Answer 6:
如果你只需要你的CSS被应用到一个特定的观点,我用我的控制器内这个方便的片断:
$("body").addClass("mystate");
$scope.$on("$destroy", function() {
$("body").removeClass("mystate");
});
这将一个类添加到我的body
标记时的状态的负载,并删除它时,状态被破坏(即有人改变页)。 这解决了我只需要CSS相关的问题在我的应用程序应用到一个状态。
Answer 7:
'use strict';
angular.module('app')
.run(
[
'$rootScope', '$state', '$stateParams',
function($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]
)
.config(
[
'$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider
.otherwise('/app/dashboard');
$stateProvider
.state('app', {
abstract: true,
url: '/app',
templateUrl: 'views/layout.html'
})
.state('app.dashboard', {
url: '/dashboard',
templateUrl: 'views/dashboard.html',
ncyBreadcrumb: {
label: 'Dashboard',
description: ''
},
resolve: {
deps: [
'$ocLazyLoad',
function($ocLazyLoad) {
return $ocLazyLoad.load({
serie: true,
files: [
'lib/jquery/charts/sparkline/jquery.sparkline.js',
'lib/jquery/charts/easypiechart/jquery.easypiechart.js',
'lib/jquery/charts/flot/jquery.flot.js',
'lib/jquery/charts/flot/jquery.flot.resize.js',
'lib/jquery/charts/flot/jquery.flot.pie.js',
'lib/jquery/charts/flot/jquery.flot.tooltip.js',
'lib/jquery/charts/flot/jquery.flot.orderBars.js',
'app/controllers/dashboard.js',
'app/directives/realtimechart.js'
]
});
}
]
}
})
.state('ram', {
abstract: true,
url: '/ram',
templateUrl: 'views/layout-ram.html'
})
.state('ram.dashboard', {
url: '/dashboard',
templateUrl: 'views/dashboard-ram.html',
ncyBreadcrumb: {
label: 'test'
},
resolve: {
deps: [
'$ocLazyLoad',
function($ocLazyLoad) {
return $ocLazyLoad.load({
serie: true,
files: [
'lib/jquery/charts/sparkline/jquery.sparkline.js',
'lib/jquery/charts/easypiechart/jquery.easypiechart.js',
'lib/jquery/charts/flot/jquery.flot.js',
'lib/jquery/charts/flot/jquery.flot.resize.js',
'lib/jquery/charts/flot/jquery.flot.pie.js',
'lib/jquery/charts/flot/jquery.flot.tooltip.js',
'lib/jquery/charts/flot/jquery.flot.orderBars.js',
'app/controllers/dashboard.js',
'app/directives/realtimechart.js'
]
});
}
]
}
})
);
文章来源: How to include view/partial specific styling in AngularJS