jQuery:如果完成,按需加载css +回调
我想按需加载CSS文件(通过例如运行XML HTTP请求,返回要加载的CSS文件),例如style1.css , style2.css ..
那么jQuery(或插件)中有一种方法吗?
- 批量加载多个文件+将所有这些CSS文件添加到dom中
- 完成加载时:触发回调(如警告“所有样式表已完成加载!”);
这个想法是:通过xmlhttp
加载html
,加载+添加所需的 css文件,然后 – 在完成任何事情后,显示该html
。
任何的想法?
感谢名单!
如何使用所请求的回调加载多个 CSS文件
请注意,如果没有xdomain权限,$ .get将只加载本地文件
工作演示
$.extend({ getCss: function(urls, callback, nocache){ if (typeof nocache=='undefined') nocache=false; // default don't refresh $.when( $.each(urls, function(i, url){ if (nocache) url += '?_ts=' + new Date().getTime(); // refresh? $.ajax({ url: url, cache: true, // set this to false if each CSS file // must refresh and not use a cached version success: function(){ $('', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head'); } }); }) ).then(function(){ if (typeof callback=='function') callback(); }); }, });
var cssfiles = [‘/ css / normalize.css?jobofferinsidebar’,’/ css / trip.css?jobofferinsidebar’];
$ .getCss(cssfiles,function(){console.log(’all css loaded’);}); 用法
var cssfiles=['/css/normalize.css', '/css/tricks.css']; $.getManyCss(cssfiles, function(){ // do something, eg console.log('all css loaded'); });
强制刷新css文件添加true
$.getManyCss(cssfiles, function(){ // do something, eg console.log('all css loaded'); }, true);
@Popnoodles给出的答案是不正确的,因为在加载所有项之后不执行回调,而是在$ .each循环完成时执行。 原因是, $.each
操作不返回Deferred对象( $.each
预期)。
这是一个更正的例子:
$.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(){ $('', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head'); }); }) ).then(function(){ if (typeof callback=='function') callback(); }); } });
我将如何加载它:
$(document).ready( function() { var css = jQuery(""); css.attr({ rel: "stylesheet", type: "text/css", href: "path/to/file/style.css" }); $("head").append(css); });
您正在尝试实现资源的延迟加载。 有不同的插件来处理这种行为。
我可以说出这两个名字:
- Jquery插件
- 懒
来自插件页面的两个片段显示它的用途:
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();
我认为解决方案可以改进一点……首先,当你使用这行代码时:
... $.get(url, function(){ $('', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head'); }); ...
你真的要进行2次调用来检索css:首先是在$.get
本身,第二次是将追加到
head
。 删除$.get
也将检索css,但只需检索一次:
... $('', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head'); ...
但是如果你在调用回调函数之前需要做更多事情(例如加载脚本文件)同时检索这些css’,我认为更好的方法是使用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 = $('', { 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 });
这样,如果某些css需要一些时间来加载,则在检索所有css之前不会执行回调函数。
如果要加载多个CSS文件,但希望逐个加载它们,可以使用以下解决方案:
var getCss = function (url, callback) { $.get(url, function () { $('', {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'];
然后定义将调用数组中每个css文件的回调函数
var callback = function (index) { getCss(cssfiles[index], function () { if (index + 1 < cssfiles.length) { callback(index + 1); } }); };
然后通过给出索引来启动第一个css文件的函数
callback(0);
如果你想通过动态(读取:按需),你可以修改Whit对loadCssFile()
的响应,并使用你想要加载的文件调用它。
function loadCssFile(pathToFile) { var css = jQuery(""); css.attr({ rel: "stylesheet", type: "text/css", href: pathToFile }); $("head").append(css); }
这不需要CSS文件(S)加载超过一次
从其他已建立的答案开始,我设法得到了这个,它似乎与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; $('').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对其进行了测试。 一切似乎都很好。