我想按需加载CSS文件(例如通过运行XML HTTP请求返回要加载的CSS文件,例如style1.css, style2.css等),那么在jQuery中(或者插件中)有办法实现吗?
- 批量加载多个文件并将所有CSS文件添加到DOM中
- 当加载完成时:触发回调函数(例如弹出“所有样式表已完成加载!”);
思路是:通过xmlhttp
加载html
,加载和添加必需的CSS文件,然后等待所有内容都加载完毕后,再显示html
。
有什么好的想法吗?
谢谢!
$.extend({
getManyCss: function(urls, callback, nocache){
if (typeof nocache=='undefined') nocache=false; // default don't refresh
$.when.apply($,
$.map(urls, function(url){
if (nocache) url += '?_ts=' + new Date().getTime(); // refresh?
return $.get(url, function(){
$('<link>', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head');
});
})
).then(function(){
if (typeof callback=='function') callback();
});
},
});
使用方法
var cssfiles=['https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css', 'https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/cerulean/bootstrap.min.css'];
$.getManyCss(cssfiles, function(){
// do something, e.g.
console.log('all css loaded');
});
要强制刷新 CSS 文件,请添加 true。
$.getManyCss(cssfiles, function(){
// do something, e.g.
console.log('all css loaded');
}, true);
$.each
循环结束后执行的。原因是 $.each
操作不返回 Deferred 对象($.when
期望获得这种对象)。$.extend({
getCss: function(urls, callback, nocache){
if (typeof nocache=='undefined') nocache=false; // default don't refresh
$.when.apply($,
$.map(urls, function(url){
if (nocache) url += '?_ts=' + new Date().getTime(); // refresh?
return $.get(url, function(){
$('<link>', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head');
});
})
).then(function(){
if (typeof callback=='function') callback();
});
}
});
function(i, url)
中交换i
和url
的位置才能真正地使其工作。 - spaceman$(document).ready( function() {
var css = jQuery("<link>");
css.attr({
rel: "stylesheet",
type: "text/css",
href: "path/to/file/style.css"
});
$("head").append(css);
});
我认为这个解决方案可以做些改进... 首先,在使用以下代码行时:
...
$.get(url, function(){
$('<link>', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head');
});
...
你实际上进行了两次调用来获取css: 第一次是在$.get
中,第二次是将<link>
添加到head
时。 如果删除$.get
,也会获取css,但只需要一次:
...
$('<link>', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head');
...
但是,如果在调用回调函数之前需要执行更多操作(例如加载脚本文件),我认为更好的方法是使用promises而不是when...then
解决方案。你可以这样做:
var requests = []; //array which will contain every request we want to do before calling the callback function
$.map(urls, function(url) { //urls is the array of css files we want to load
var defer = $.Deferred();
defer.promise();
//we add the deferred object to the requests array
requests.push(defer);
var cssEl = $('<link>', { rel: 'stylesheet', type: 'text/css', 'href': url });
cssEl.appendTo('head').on("load", function() {
defer.resolve();
});
});
var anotherRequest = $.ajax({...}); //eg. a script file
requests.push(anotherRequest);
$.when.apply($, requests).done(function() {
// callback when all requests are done
});
您正在尝试实现资源的延迟加载。
有不同的插件可以处理这种行为。
我可以提到这两个:
来自插件页面的两个片段以展示它的使用:
Jquery 插件
$.plugins({ path: '/scripts/', plugins: [
{ id:'box', js:'box.js', css:'box/styles.css', sel:'a[rel*=box]', ext:'box', fn:'box' },
]});
jQuery(document).ready(function($){
$('a').box();
});
依赖惰性加载:
$.lazy('ui.draggable.js','draggable',{
'css':['modal.css','drag.css'],
'js':['ui.core.js']
});
// And then you use you plugins as you always do
$("#draggable").draggable();
这不需要加载CSS文件超过一次
在其他已有答案的基础上,我设法想出了这个解决方案,它似乎类似于jQuery.getScript()
:
(function($){
$.extend({
getCss: function(url, success) {
if ($("head").children("style[data-url='"+url+"']").length) {
console.warn("CSS file already loaded: "+url);
}
var deferred = $.Deferred(function(defer){
$.ajax({
url: url
,context: {defer:defer,url:url}
,dataType: 'text'
,cache: (function(){
var cache = $.ajaxSetup().cache;
if (cache === undefined) {cache = false;}
return cache;
})()
})
.then(
function(css, textStatus, jqXHR){
css = "\n\n/* CSS dynamically loaded by jQuery */\n\n"+css;
$('<style type="text/css" data-url="'+this.url+'">'+css+'</style>').appendTo("head");
this.defer.resolve(css, textStatus, jqXHR);
}
,function(jqXHR, textStatus, errorThrown){
this.defer.reject(jqXHR, textStatus, errorThrown);
}
);
});
if ($.isFunction(success)) {deferred.done(success);}
return deferred;
}
});
})(jQuery);
它不会多次加载请求的文件,这要求CSS内容在头部静态存储。但是,考虑到加载/评估JavaScript与浏览器呈现样式的可访问性不同,这是有道理的。
$.getCss('path/to/css/file.css')
.done(function(){
console.log("Worked");
})
.fail(function(){
console.log("Failed");
});
到目前为止,我已经在Chrome、IE和Firefox上进行了测试。所有浏览器似乎都能正常工作。
loadCssFile()
并调用要加载的文件。function loadCssFile(pathToFile) {
var css = jQuery("<link>");
css.attr({
rel: "stylesheet",
type: "text/css",
href: pathToFile
});
$("head").append(css);
}
var getCss = function (url, callback) {
$.get(url, function () {
$('<link>', {rel: 'stylesheet', type: 'text/css', 'href': url}).appendTo('head');
if (typeof callback == 'function') callback();
});
};
先定义函数,然后定义包含所需 CSS 文件的数组
var cssfiles = ['css/pic1.css', 'css/pic2.css', 'css/pic3.css', 'css/pic4.css', 'css/pic5.css', 'css/pic6.css', 'css/pic7.css', 'css/pic8.css', 'css/pic9.css'];
var callback = function (index) {
getCss(cssfiles[index], function () {
if (index + 1 < cssfiles.length) {
callback(index + 1);
}
});
};
然后通过给出第一个CSS文件的索引来启动函数
callback(0);
<link>
何时被添加。一个简单的修复方法是if (typeof callback=='function') setTimeout(callback, 500);
延迟为0适用于某些问题,但并不足够。一定有更简洁的方法... - Popnoodles<link>
附加到head
中。 - rolebi