Динамическая загрузка файла CSS с использованием JavaScript с обратным вызовом без JQuery - PullRequest
31 голосов
/ 04 апреля 2011

Я пытаюсь загрузить файл css динамически, используя javascript, и не могу использовать любую другую библиотеку js (например, jQuery).

Файл css загружается, но у меня не получается получить обратный вызов, чтобы он работал,Ниже приведен код, который я использую

var callbackFunc = function(){
    console.log('file loaded');     
};
var head = document.getElementsByTagName( "head" )[0];
var fileref=document.createElement("link");
    fileref.setAttribute("rel", "stylesheet");
    fileref.setAttribute("type", "text/css");
    fileref.setAttribute("href", url);

    fileref.onload  = callbackFunc;
    head.insertBefore( fileref, head.firstChild );

Использование следующего кода для добавления тега сценария для загрузки файла js работает и вызывает обратный вызов:

var callbackFunc = function(){
    console.log('file loaded');     
};

var script = document.createElement("script");

script.setAttribute("src",url);
script.setAttribute("type","text/javascript");

script.onload  = callbackFunc ;

head.insertBefore( script, head.firstChild );

Я что-то не так делаюВот?Любой другой метод, который может помочь мне достичь этого, будет высоко ценится?

Ответы [ 6 ]

37 голосов
/ 04 апреля 2011

К сожалению, в большинстве современных браузеров отсутствует поддержка загрузки таблиц стилей. Есть решение, которое я нашел с небольшим поиском в Google.

Цитируется по: http://thudjs.tumblr.com/post/637855087/stylesheet-onload-or-lack-thereof

Основы

Самая простая реализация этого может быть выполнена в 30 строк - не зависящих от фреймворка - код JavaScript:

function loadStyleSheet( path, fn, scope ) {
   var head = document.getElementsByTagName( 'head' )[0], // reference to document.head for appending/ removing link nodes
       link = document.createElement( 'link' );           // create the link node
   link.setAttribute( 'href', path );
   link.setAttribute( 'rel', 'stylesheet' );
   link.setAttribute( 'type', 'text/css' );

   var sheet, cssRules;
// get the correct properties to check for depending on the browser
   if ( 'sheet' in link ) {
      sheet = 'sheet'; cssRules = 'cssRules';
   }
   else {
      sheet = 'styleSheet'; cssRules = 'rules';
   }

   var interval_id = setInterval( function() {                     // start checking whether the style sheet has successfully loaded
          try {
             if ( link[sheet] && link[sheet][cssRules].length ) { // SUCCESS! our style sheet has loaded
                clearInterval( interval_id );                      // clear the counters
                clearTimeout( timeout_id );
                fn.call( scope || window, true, link );           // fire the callback with success == true
             }
          } catch( e ) {} finally {}
       }, 10 ),                                                   // how often to check if the stylesheet is loaded
       timeout_id = setTimeout( function() {       // start counting down till fail
          clearInterval( interval_id );             // clear the counters
          clearTimeout( timeout_id );
          head.removeChild( link );                // since the style sheet didn't load, remove the link node from the DOM
          fn.call( scope || window, false, link ); // fire the callback with success == false
       }, 15000 );                                 // how long to wait before failing

   head.appendChild( link );  // insert the link node into the DOM and start loading the style sheet

   return link; // return the link node;
}

Это позволит вам загрузить таблицу стилей с помощью функции обратного вызова onload:

loadStyleSheet( '/path/to/my/stylesheet.css', function( success, link ) {
   if ( success ) {
      // code to execute if the style sheet was loaded successfully
   }
   else {
      // code to execute if the style sheet failed to successfully
   }
} );

Или, если вы хотите, чтобы ваш обратный вызов поддерживал его контекст / контекст, вы можете сделать что-то вроде этого:

loadStyleSheet( '/path/to/my/stylesheet.css', this.onComplete, this );
5 голосов
/ 11 мая 2016

Некоторое время назад я сделал для этого библиотеку, она называется Дизель , надеюсь, это поможет

Пример: https://jsfiddle.net/sunrising/qk0ybtnb/

var googleFont = 'https://fonts.googleapis.com/css?family=Lobster';
var jquery = 'https://code.jquery.com/jquery.js';
var bootstrapCss = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css';
var bootstrapJs = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js';
var smokeCss = 'https://rawgit.com/alfredobarron/smoke/master/dist/css/smoke.min.css';
var smokeJs = 'https://rawgit.com/alfredobarron/smoke/master/dist/js/smoke.min.js';

// push links into an array in the correct order
var extRes = [];
extRes.push(googleFont);
extRes.push(bootstrapCss);
extRes.push(smokeCss);
extRes.push(jquery);
extRes.push(bootstrapJs);
extRes.push(smokeJs);

// let this happen
dysel({
  links: extRes,
  callback: function() {
    alert('everything is now loaded, this is awesome!');
  }, // optional
  nocache: false, // optional
  debug: false // optional
});
5 голосов
/ 04 апреля 2011

Вы можете сделать пустую ссылку CSS в своем HTML-файле и дать ссылку идентификатор.например,

<link id="stylesheet_css" rel="stylesheet" type="text/css" href="css/dummy.css?"/>

, затем вызовите его с идентификатором и измените атрибут 'href'

4 голосов
/ 02 декабря 2016

Этот ванильный JS-подход работает во всех современных браузерах:

let loadStyle = function(url) {
  return new Promise((resolve, reject) => {
    let link    = document.createElement('link');
    link.type   = 'text/css';
    link.rel    = 'stylesheet';
    link.onload = () => { resolve(); console.log('style has loaded'); };
    link.href   = url;

    let headScript = document.querySelector('script');
    headScript.parentNode.insertBefore(link, headScript);
  });
};

// works in IE 10, 11 and Safari/Chrome/Firefox/Edge
// add an ES6 polyfill for the Promise (or rewrite to use a callback)
1 голос
/ 09 августа 2015

Вот как мы это делаем. С помощью «requestAnimationFrame» (или возврата к простому событию «load», если оно не помогло).

Кстати, именно так Google рекомендует в своем руководстве «Скорость страницы»: https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery

<script>
    function LoadCssFile(cssPath) {
        var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = cssPath;
        var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h);
    }
    var cb = function() {
        LoadCssFile('file1.css');
        LoadCssFile('file2.css');
    };
    var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    if (raf) raf(cb);
    else window.addEventListener('load', cb);
</script>
0 голосов
/ 21 июня 2013

yepnope.js может загрузить CSS и выполнить обратный вызов по завершении. например,

yepnope([{
  load: "styles.css",
  complete: function() {
    console.log("oooooo. shiny!");
  }
}]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...