【问题标题】:Dynamically Importing JavaScript动态导入 JavaScript
【发布时间】:2012-06-07 13:06:23
【问题描述】:

请问,将 JavaScript (.js) 文件动态导入父 JavaScript 代码的正确方法是什么?

我正在使用以下代码,但似乎不正确:

    function loadjscssfile(filename, filetype)
{
    //if filename is a external JavaScript file
    if (filetype=="js")
    {
        var fileref=document.createElement('script');
        fileref.setAttribute("type","text/javascript");
        fileref.setAttribute("src", filename);
    }
    //if filename is an external CSS file
    else if (filetype=="css")
    {
        var fileref=document.createElement("link");
        fileref.setAttribute("rel", "stylesheet");
        fileref.setAttribute("type", "text/css");
        fileref.setAttribute("href", filename);
    }
    if (typeof fileref!="undefined")
    document.getElementsByTagName("head")[0].appendChild(fileref)
}

我认为,代码不正确,因为在主 JavaScript 代码中,我无法读取导入代码中定义的变量,例如:

var fileRef = loadjscssfile('Language/svk.js', 'js');
alert("Pet Name: " + PETNAME);

导入的 svk.js 文件包含唯一的代码:

// JavaScript Document
var PETNAME = "Beauty";

谢谢。

【问题讨论】:

  • 检查js文件导入是否成功。 den 尝试访问加载的 js 中定义的变量。
  • @Sarfraz:嗨,是的,tye 代码已导入,我可以确认一下,我将 alert("Pet Name: " + PETNAME); 放入导入的代码中,然后运行,我看到了警告框具有适当的价值。但是,如果将alert("Pet Name: " + PETNAME); 移动到主文件中,我无法获取PETNAME 的值
  • 您必须记住,文件加载和解析需要一些时间,您无法在调用函数后立即访问其内容。也许在您导入的文件中,您可以在原始代码中添加对回调的函数调用,以表明导入的文件已成功加载。
  • 看看这个:stackoverflow.com/questions/950087/… 有一个很好的答案和一个很好的 jQuery 示例,在脚本被读取/加载后使用变量
  • @Yaniro:您好,感谢您的回复。我怎么知道代码已经导入?这应该只是我导入代码的最后一行吗?请给我一个例子好吗?谢谢你的好建议,我有一些想法可以进一步探索。

标签: javascript web dynamic-html


【解决方案1】:

你不能在插入<script>标签后立即使用外部JS文件中定义的变量和函数。浏览器需要几毫秒的时间来加载文件并执行它。

您必须使用某种回调才能为您的 JavaScript 设置正确的加载顺序。

关于 JavaScript 的正确条件加载,请查看 Require.js。那里实现了异步模块定义模式。

【讨论】:

  • +1 - 嗨 Sirko。谢谢您的回答。是的,显然,我的问题并不是什么新鲜事,因为更多的人立即知道了我的问题的根源。我来看看 Require.js。
【解决方案2】:

您无法读取PETNAME 变量的原因是像这样动态注入脚本是异步且非阻塞的。这意味着您的 alert 在脚本实际加载之前执行。相反,您可能必须轮询 PETNAME 变量的存在:

var waitForPETNAME = function(){
        if (typeof PETNAME === 'undefined') {
            setTimeout(waitForPETNAME, 15);
        } else {
            // execute code that uses PETNAME
        }
    };

waitForPETNAME();

此外,动态注入元素的更简单的方法是将它们插入到第一个脚本元素之前,因为您确定必须存在脚本元素(否则您将不会执行代码)。换句话说,替换:

document.getElementsByTagName("head")[0].appendChild(fileref)

与:

var insref = document.getElementsByTagName('script')[0];
insref.parentNode.insertBefore(fileref, insref);

【讨论】:

  • +1 并感谢您的回答和其他改进想法。关于setTimeout(waitForPETNAME, 15);,我有一个问题,请问:代码在等待另一个函数调用期间是否停止?或者,代码是否继续运行,并且函数被异步调用?关于您提出的改进建议,请问我的代码在哪些方面会失败?我根本没有得到,你的代码在哪些方面更强大。很抱歉忽略了这一点。
  • 代码继续运行,异步调用超时轮询。至于改进,HTML5 不再需要 <head> 标记,或者在某些较旧的浏览器中,当脚本执行时您可能无法在此处附加。我建议的改进避免了这两种情况。
  • 我的问题的所有答案都是有效的,谢谢大家的回复。我对每个好的答案都给予 +1。但是,我只需要选择一个答案作为已接受的答案,而且由于 mVChr 为我的代码提供了有价值的改进,我想将此答案标记为已接受的答案。谢谢大家。
【解决方案3】:

svk.js中添加以下内容(变量减速后):

svkLoaded();

在主代码文件中添加以下内容:

function svkLoaded()
{
    alert("Pet Name: " + PETNAME);
}

【讨论】:

  • +1 - 出色的建议和解释。非常感谢 Yaniro。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 2021-03-03
  • 1970-01-01
  • 2021-02-03
  • 2019-10-31
  • 1970-01-01
相关资源
最近更新 更多