Css 如何在AngularJS中包含视图/局部特定样式
对于我的应用程序使用的各种视图,使用单独样式表的正确/公认方式是什么? 目前,我正在视图/部分的html顶部放置一个link元素,但有人告诉我,尽管所有现代浏览器都支持它,但这是一种不好的做法,但我可以理解为什么不支持它 另一种可能是将单独的样式表放在index.html的Css 如何在AngularJS中包含视图/局部特定样式,css,model-view-controller,angularjs,Css,Model View Controller,Angularjs,对于我的应用程序使用的各种视图,使用单独样式表的正确/公认方式是什么? 目前,我正在视图/部分的html顶部放置一个link元素,但有人告诉我,尽管所有现代浏览器都支持它,但这是一种不好的做法,但我可以理解为什么不支持它 另一种可能是将单独的样式表放在index.html的head中,但我希望它仅在以性能的名义加载其视图时加载样式表 这种做法是否不好,因为样式只有在从服务器加载css后才会生效,从而导致在缓慢的浏览器中快速闪现未格式化的内容?我还没有看到这一点,尽管我正在本地测试它 是否有方法通
head
中,但我希望它仅在以性能的名义加载其视图时加载样式表
这种做法是否不好,因为样式只有在从服务器加载css后才会生效,从而导致在缓慢的浏览器中快速闪现未格式化的内容?我还没有看到这一点,尽管我正在本地测试它
是否有方法通过传递给Angular的$routeProvider的对象加载CSS。何时加载
提前谢谢 可以在$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">');
}
/*首先检查是否已经存在-注意链接元素上使用的ID*/
/*还可以跟踪范围内的对象*/
if(!angular.element('link#myViewName').length){
角元素('head')。附加('');
}
在页面中进行预处理的最大好处是,任何背景图像都已经存在,而且FOUC@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">');
}
}
}
})
您可以随意命名“键”,在我的例子中,我称之为“样式””
对于该值,您有两个选项:
- 如果它是字符串,则它是服务的别名
- 如果它是函数,则会将其注入并处理返回值
作为依赖关系
这里的要点是,在实例化控制器并触发$routeChangeSuccess事件之前,将执行函数中的代码
希望能有所帮助。我知道这个问题现在已经很老了,但在对这个问题的各种解决方案进行了大量研究之后,我想我可能已经找到了更好的解决方案
更新1:发布此答案后,我将所有这些代码添加到我发布到GitHub的一个简单服务中。回购协议位于。请随时查看以了解更多信息
更新2:如果您只需要一个轻量级的解决方案来为路由引入样式表,那么这个答案非常好。如果您想要一个更完整的解决方案来管理整个应用程序中的按需样式表,您可能需要签出。它提供了更细粒度的功能
如果将来有人对此感兴趣,以下是我的想法:
1。为
元素创建自定义指令:
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;
});
}
});
}
};
}
]);
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
属性,并根据需要附加/删除这些
标记。请注意,在路由上指定css
属性是完全可选的,因为在'/some/route/2'
示例中省略了该属性。如果路由没有css
属性,则
指令将对该路由不做任何操作。还要注意,每个路由甚至可以有多个特定于页面的样式表,如上面的'/some/route/3'
示例,其中css
属性是该路由所需样式表的相对路径数组
3。你完成了
这两件事设置了所有需要的东西,并且在我看来,它使用了尽可能干净的代码
希望这能帮助像我一样在这个问题上苦苦挣扎的其他人。太棒了,谢谢!!只需进行一些调整,即可使用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);
});
});
}
}
}]);
var-app=app | | angular.module('app',[]);
app.directive('head',['$rootScope','$compile','$state',函数($rootScope,$compile,$state){
返回{
限制:'E',
链接:功能($scope、elem、attrs、ctrls){
var html='';
var el=$compile(html)($scope)
附加元素(el);
$scope.routeStyles={};
函数applyStyles(状态、操作){
var sheets=state?state.css:null;
if(state.parent){
var parentState=$state.get(state.parent)
applyStyles(父状态、操作);
}
若有(张){
如果(!Array.isArray(张)){
纸张=[纸张];
}
角度。forEach(表,函数(表){
行动(表);
});
}
}
$rootScope.$on(“$stateChangeStart”,函数(事件、toState、toParams、fromState、fromParams){
applyStyles(来自状态、函数(工作表){
删除$scope.routeStyles[表格];
console.log(“>>删除>>”,工作表);
});
applyStyles(状态、功能(表){
$scope.rout
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);
});
});
}
}
}]);
$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'
}
});
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();
});
$("body").addClass("mystate");
$scope.$on("$destroy", function() {
$("body").removeClass("mystate");
});
$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'
]
});
}
]
}
})
);