Dynamisch geladen JS binnen JS [DUPLICEER]

Ik heb een dynamische webpagina waar ik een extern JS-bestand nodig heb (onder een IF-conditie) in een ander JavaScript-bestand.

Ik heb geprobeerd om naar een haalbare oplossing te zoeken, maar het werkte niet.

Ik heb geprobeerd een JS-bestand te laden aan de DOM met document.createElement()Maar het werkte ook niet. Blijkbaar werd de JS in de DOM geladen, maar was niet toegankelijk in het huidige JS-bestand.

Oplossing in jQuery is ook goed


Antwoord 1, Autoriteit 100%

JQuery’s $.getScript()is een buggy soms, dus ik gebruik mijn eigen implementatie ervan zoals:

jQuery.loadScript = function (url, callback) {
    jQuery.ajax({
        url: url,
        dataType: 'script',
        success: callback,
        async: true
    });
}

en gebruik het zoals:

if (typeof someObject == 'undefined') $.loadScript('url_to_someScript.js', function(){
    //Stuff to do after someScript has loaded
});

Antwoord 2, Autoriteit 466%

Mijn gok is dat je in je Dom-Only-oplossing iets hebt gedaan als:

var script = document.createElement('script');
script.src = something;
//do stuff with the script

Allereerst werken dat niet omdat het script niet aan de documentboom wordt toegevoegd, dus het zal niet worden geladen. Bovendien gaat zelfs wanneer u het doet, de uitvoering van JavaScript voortduurt, terwijl het andere script wordt geladen, zodat de inhoud ervan niet beschikbaar is totdat dat script volledig is geladen.

U kunt luisteren naar het script’s loadevenement en doen dingen met de resultaten zoals u zou doen. Dus:

var script = document.createElement('script');
script.onload = function () {
    //do stuff with the script
};
script.src = something;
document.head.appendChild(script); //or something of the likes

Antwoord 3, autoriteit 60%

Ik moet dit vaak doen, dus ik gebruik dit:

var loadJS = function(url, implementationCode, location){
    //url is URL of external file, implementationCode is the code
    //to be called from the file, location is the location to 
    //insert the <script> element
    var scriptTag = document.createElement('script');
    scriptTag.src = url;
    scriptTag.onload = implementationCode;
    scriptTag.onreadystatechange = implementationCode;
    location.appendChild(scriptTag);
};
var yourCodeToBeCalled = function(){
//your code goes here
}
loadJS('yourcode.js', yourCodeToBeCalled, document.body);

Zie deze site voor meer informatie Hoe voeg ik een JavaScript toe bestand in een ander JavaScript-bestand?, wat de bron is van mijn functie-idee.


Antwoord 4, autoriteit 17%

Je mag de js dynamisch in de pagina laden, niet een ander js-bestand

je moet het getScriptgebruiken om het js-bestand te laden

$.getScript("ajax/test.js", function(data, textStatus, jqxhr) {
console.log(data); //data returned
console.log(textStatus); //success
console.log(jqxhr.status); //200
console.log('Load was performed.');
});

Antwoord 5, autoriteit 11%

Necromance.

Ik gebruik dit om afhankelijke scripts te laden;
Het werkt met IE8 + zonder toevoeging van een afhankelijkheid van een andere bibliotheek zoals jQuery!

var cScriptLoader = (function ()
{
    function cScriptLoader(files)
    {
        var _this = this;
        this.log = function (t)
        {
            console.log("ScriptLoader: " + t);
        };
        this.withNoCache = function (filename)
        {
            if (filename.indexOf("?") === -1)
                filename += "?no_cache=" + new Date().getTime();
            else
                filename += "&no_cache=" + new Date().getTime();
            return filename;
        };
        this.loadStyle = function (filename)
        {
            // HTMLLinkElement
            var link = document.createElement("link");
            link.rel = "stylesheet";
            link.type = "text/css";
            link.href = _this.withNoCache(filename);
            _this.log('Loading style ' + filename);
            link.onload = function ()
            {
                _this.log('Loaded style "' + filename + '".');
            };
            link.onerror = function ()
            {
                _this.log('Error loading style "' + filename + '".');
            };
            _this.m_head.appendChild(link);
        };
        this.loadScript = function (i)
        {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = _this.withNoCache(_this.m_js_files[i]);
            var loadNextScript = function ()
            {
                if (i + 1 < _this.m_js_files.length)
                {
                    _this.loadScript(i + 1);
                }
            };
            script.onload = function ()
            {
                _this.log('Loaded script "' + _this.m_js_files[i] + '".');
                loadNextScript();
            };
            script.onerror = function ()
            {
                _this.log('Error loading script "' + _this.m_js_files[i] + '".');
                loadNextScript();
            };
            _this.log('Loading script "' + _this.m_js_files[i] + '".');
            _this.m_head.appendChild(script);
        };
        this.loadFiles = function ()
        {
            // this.log(this.m_css_files);
            // this.log(this.m_js_files);
            for (var i = 0; i < _this.m_css_files.length; ++i)
                _this.loadStyle(_this.m_css_files[i]);
            _this.loadScript(0);
        };
        this.m_js_files = [];
        this.m_css_files = [];
        this.m_head = document.getElementsByTagName("head")[0];
        // this.m_head = document.head; // IE9+ only
        function endsWith(str, suffix)
        {
            if (str === null || suffix === null)
                return false;
            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        }
        for (var i = 0; i < files.length; ++i)
        {
            if (endsWith(files[i], ".css"))
            {
                this.m_css_files.push(files[i]);
            }
            else if (endsWith(files[i], ".js"))
            {
                this.m_js_files.push(files[i]);
            }
            else
                this.log('Error unknown filetype "' + files[i] + '".');
        }
    }
    return cScriptLoader;
})();
var ScriptLoader = new cScriptLoader(["foo.css", "Scripts/Script4.js", "foobar.css", "Scripts/Script1.js", "Scripts/Script2.js", "Scripts/Script3.js"]);
ScriptLoader.loadFiles();

Als je geïnteresseerd bent in de typescript-versie die is gebruikt om dit te maken:

class cScriptLoader {
    private m_js_files: string[];
    private m_css_files: string[];
    private m_head:HTMLHeadElement;
    private log = (t:any) =>
    {
        console.log("ScriptLoader: " + t);
    }
    constructor(files: string[]) {
        this.m_js_files = [];
        this.m_css_files = [];
        this.m_head = document.getElementsByTagName("head")[0];
        // this.m_head = document.head; // IE9+ only
        function endsWith(str:string, suffix:string):boolean 
        {
            if(str === null || suffix === null)
                return false;
            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        }
        for(let i:number = 0; i < files.length; ++i) 
        {
            if(endsWith(files[i], ".css"))
            {
                this.m_css_files.push(files[i]);
            }
            else if(endsWith(files[i], ".js"))
            {
                this.m_js_files.push(files[i]);
            }
            else
                this.log('Error unknown filetype "' + files[i] +'".');
        }
    }
    public withNoCache = (filename:string):string =>
    {
        if(filename.indexOf("?") === -1)
            filename += "?no_cache=" + new Date().getTime();
        else
            filename += "&no_cache=" + new Date().getTime();
        return filename;    
    }
    public loadStyle = (filename:string) =>
    {
        // HTMLLinkElement
        let link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = this.withNoCache(filename);
        this.log('Loading style ' + filename);
        link.onload = () =>
        {
            this.log('Loaded style "' + filename + '".');
        };
        link.onerror = () =>
        {
            this.log('Error loading style "' + filename + '".');
        };
        this.m_head.appendChild(link);
    }
    public loadScript = (i:number) => 
    {
        let script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = this.withNoCache(this.m_js_files[i]);
        var loadNextScript = () => 
        {
            if (i + 1 < this.m_js_files.length)
            {
                this.loadScript(i + 1);
            }
        }
        script.onload = () =>
        {
            this.log('Loaded script "' + this.m_js_files[i] + '".');
            loadNextScript();
        };
        script.onerror = () =>
        {
            this.log('Error loading script "' + this.m_js_files[i] + '".');
            loadNextScript();
        };
        this.log('Loading script "' + this.m_js_files[i] + '".');
        this.m_head.appendChild(script);
    }
    public loadFiles = () => 
    {
        // this.log(this.m_css_files);
        // this.log(this.m_js_files);
        for(let i:number = 0; i < this.m_css_files.length; ++i)
            this.loadStyle(this.m_css_files[i])
        this.loadScript(0);
    }
}
var ScriptLoader = new cScriptLoader(["foo.css", "Scripts/Script4.js", "foobar.css", "Scripts/Script1.js", "Scripts/Script2.js", "Scripts/Script3.js"]);
ScriptLoader.loadFiles();

Als het is om een dynamische lijst met scripts te laden, schrijf de scripts dan in een attribuut, zoals data-main, b.v.
<script src="scriptloader.js" data-main="file1.js,file2.js,file3.js,etc." ></script>
en doe een element.getAttribute("data-main").split(',')

zoals

var target = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  // Note: this is for IE as IE doesn't support currentScript
  // this does not work if you have deferred loading with async
  // e.g. <script src="..." async="async" ></script>
  // https://web.archive.org/web/20180618155601/https://www.w3schools.com/TAgs/att_script_async.asp
  return scripts[scripts.length - 1];
})();
target.getAttribute("data-main").split(',')

om de lijst te verkrijgen.


Antwoord 6, autoriteit 5%

De jQuery.getScript()methode is een afkorting van de Ajax-functie (met het dataType-attribuut: $.ajax({ url: url,dataType: "script"}))

Als je wilt dat de scripts in cache kunnen worden opgeslagen, gebruik dan RequireJSof volg het voorbeeld van jQuery over het uitbreiden van de jQuery.getScriptmethode vergelijkbaar met het volgende.

jQuery.cachedScript = function( url, options ) {
  // Allow user to set any option except for dataType, cache, and url
  options = $.extend( options || {}, {
    dataType: "script",
    cache: true,
    url: url
  });
  // Use $.ajax() since it is more flexible than $.getScript
  // Return the jqXHR object so we can chain callbacks
  return jQuery.ajax( options );
};
// Usage
$.cachedScript( "ajax/test.js" ).done(function( script, textStatus ) {
  console.log( textStatus );
});

Referentie: jQuery.getScript() | jQuery API-documentatie


Antwoord 7, autoriteit 3%

jQuery heeft $.getScript():

Beschrijving: laad een JavaScript-bestand van de server met behulp van een GET HTTP-verzoek en voer het vervolgens uit.


Antwoord 8, autoriteit 3%

Je kunt het doen met JQuery:

$.getScript("ajax/test.js", function(data, textStatus, jqxhr) {
  console.log(data); //data returned
  console.log(textStatus); //success
  console.log(jqxhr.status); //200
  console.log('Load was performed.');
});

deze link zou moeten helpen:
http://api.jquery.com/jQuery.getScript/


Antwoord 9, autoriteit 3%

Ik raad aan om requiredjs te gebruiken met AMD javascript-klassebestanden

goed voorbeeld van hoe je het hier kunt gebruiken

http://www.sitepoint.com/understanding -requirejs-for-effectieve-javascript-module-loading/


Antwoord 10, autoriteit 3%

Om mijn plug-in te schrijven, moest ik externe scripts en stijlen in een JS-bestand laden, die allemaal vooraf waren gedefinieerd. Om dit te bereiken heb ik het volgende gedaan:

   this.loadRequiredFiles = function (callback) {
        var scripts = ['xx.js', 'yy.js'];
        var styles = ['zz.css'];
        var filesloaded = 0;
        var filestoload = scripts.length + styles.length;
        for (var i = 0; i < scripts.length; i++) {
            log('Loading script ' + scripts[i]);
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = scripts[i];
            script.onload = function () {
                log('Loaded script');
                log(this);
                filesloaded++;  // (This means increment, i.e. add one)
                finishLoad();
            };
            document.head.appendChild(script);
        }
        for (var i = 0; i < styles.length; i++) {
            log('Loading style ' + styles[i]);
            var style = document.createElement('link');
            style.rel = 'stylesheet';
            style.href = styles[i];
            style.type = 'text/css';
            style.onload = function () {
                log('Loaded style');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(style);
        }
        function finishLoad() {
            if (filesloaded === filestoload) {
                callback();
            }
        }
    };

Meer van het script in context:

function myPlugin() {
    var opts = {
        verbose: false
    };                          ///< The options required to run this function
    var self = this;            ///< An alias to 'this' in case we're in jQuery                         ///< Constants required for this function to work
    this.getOptions = function() {
        return opts;
    };
    this.setOptions = function(options) {
        for (var x in options) {
            opts[x] = options[x];
        }
    };
    /**
     * @brief Load the required files for this plugin
     * @param {Function} callback A callback function to run when all files have been loaded
     */
    this.loadRequiredFiles = function (callback) {
        var scripts = ['xx.js', 'yy.js'];
        var styles = ['zz.css'];
        var filesloaded = 0;
        var filestoload = scripts.length + styles.length;
        for (var i = 0; i < scripts.length; i++) {
            log('Loading script ' + scripts[i]);
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = scripts[i];
            script.onload = function () {
                log('Loaded script');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(script);
        }
        for (var i = 0; i < styles.length; i++) {
            log('Loading style ' + styles[i]);
            var style = document.createElement('link');
            style.rel = 'stylesheet';
            style.href = styles[i];
            style.type = 'text/css';
            style.onload = function () {
                log('Loaded style');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(style);
        }
        function finishLoad() {
            if (filesloaded === filestoload) {
                callback();
            }
        }
    };
    /**
     * @brief Enable user-controlled logging within this function
     * @param {String} msg The message to log
     * @param {Boolean} force True to log message even if user has set logging to false
     */
    function log(msg, force) {
        if (opts.verbose || force) {
            console.log(msg);
        }
    }
    /**
     * @brief Initialise this function
     */
    this.init = function() {
        self.loadRequiredFiles(self.afterLoadRequiredFiles);
    };
    this.afterLoadRequiredFiles = function () {
        // Do stuff
    };
}

Antwoord 11

Je kunt de $.getScript()-methode van jQuery gebruiken om dit te doen, maar als je een meer volledige functie wilt, yepnope.jsis jouw keuze. Het ondersteunt het voorwaardelijk laden van scripts en stylesheets en is gemakkelijk te gebruiken.


Antwoord 12

Hier is een kleine lib om javascript- en CSS-bestanden dynamisch te laden:

https://github.com/todotresde/javascript-loader

Ik denk dat het handig is om css- en js-bestanden in volgorde en dynamisch te laden.

Ondersteuning om uit te breiden om elke gewenste lib te laden, en niet alleen het hoofdbestand, je kunt het gebruiken om aangepaste bestanden te laden.

I.E.:

<html>
<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="scripts/javascript-loader.js" type="text/javascript" charset="utf-8" ></script>    
    <script type="text/javascript">
        $(function() {
            registerLib("threejs", test);
            function test(){
                console.log(THREE);
            }
            registerLib("tinymce", draw);
            function draw(){
                tinymce.init({selector:'textarea'});
            }
        }); 
    </script>
</head>
<body>
    <textarea>Your content here.</textarea>
</body>

Antwoord 13

Als je veel bestandenmet afhankelijkhedenhebt, gebruik dan AMD/RequireJS.
http://requirejs.org/

Other episodes