在脚本加载后调用JavaScript函数

109
我有一个HTML页面,在其中通过JavaScript动态地添加HTML,如下所示:
<script type="text/javascript" src="/myapp/htmlCode"></script>
我想调用一个 JavaScript 函数,例如 loadedContent(); ,一旦上述脚本添加了动态 HTML。有人可以帮助我如何实现吗?
答案:

我想调用一个 JavaScript 函数,例如 loadedContent(); ,一旦上述脚本添加了动态 HTML。有人可以帮助我如何实现吗?

8个回答

179

您可以不使用head.js JavaScript来实现这一点。

function loadScript( url, callback ) {
  var script = document.createElement( "script" )
  script.type = "text/javascript";
  if(script.readyState) {  // only required for IE <9
    script.onreadystatechange = function() {
      if ( script.readyState === "loaded" || script.readyState === "complete" ) {
        script.onreadystatechange = null;
        callback();
      }
    };
  } else {  //Others
    script.onload = function() {
      callback();
    };
  }

  script.src = url;
  document.getElementsByTagName( "head" )[0].appendChild( script );
}


// call the function...
loadScript(pathtoscript, function() {
  alert('script ready!'); 
});

8
FYI: onload 对于 IE 9 及更高版本是可以使用的,因此只需设置 onload 可能对大多数人来说已经足够了。 - Simon_Weaver
9
请注意,onload 会在脚本“加载”时立即启动回调函数,而不是在实际执行完成时启动,这一点令人失望。 - Ma Dude
@MaDude 你能否提供关于那个的任何文档参考? - kontrollanten
4
由于JavaScript是单线程的,所以在脚本执行完成之前不可能调用onload处理程序。这意味着onload处理程序只能在脚本开始执行之前或执行完成之后被调用。我个人从未见过前一种情况发生...从未。如果有人知道一个可重现onload处理程序可以在脚本开始执行之前被调用的案例,请告诉我们。 - GetFree
一个简单的扩展,用于加载脚本数组: for (var i=0; i - sree

38

如果您在2021年阅读此帖子,则可能更习惯Promises。如果您的目标浏览器全部支持ES6,或者您正在使用polyfill,则更现代的方法更可取。

此解决方案类似于@JaykeshPatel的答案,但基于Promise

// definition
function loadScript(scriptUrl) {
  const script = document.createElement('script');
  script.src = scriptUrl;
  document.body.appendChild(script);
  
  return new Promise((res, rej) => {
    script.onload = function() {
      res();
    }
    script.onerror = function () {
      rej();
    }
  });
}

// use
loadScript('http://your-cdn/jquery.js')
  .then(() => {
    console.log('Script loaded!');
  })
  .catch(() => {
    console.error('Script loading failed! Handle this error');
  });

你可以在res回调函数的参数中传递一些上下文变量,或者如果你的库导入了一些全局符号,你可以在那里引用它们。

例如,由于jQuery引入了全局符号$,你可以调用res($)并为其创建一个本地作用域(如果你正在使用TypeScript,并且不想在每个文件中声明模块变量,这样做非常完美,这样你就可以写成const $ = await loadScript(..))。

如果你不想传递任何参数,你可以这样简化你的代码:

script.onload = res;
script.onerror = rej;

1
script.onLoad = res; // 简化 - Kunukn
1
@Kunukn 还有一个更短的方法 return new Promise(res => script.onload = res)。但是将函数分配给 onload 可以更容易阅读,并允许您在解决时传递参数。 - Christian Vincenzo Traina

37

我遇到了同样的问题... 我的解决方案(不使用jQuery):

<script onload="loadedContent();" src ="/myapp/myCode.js"  ></script>

6
请注意:这将与严格的内容安全策略不兼容。 - Bradley
@Bradley 你确定吗?我猜加上 nonce="${nonce}" 应该可以让它工作(未经测试的猜测)。 - guettli
@guettli 不好意思,您无法对内联事件处理程序进行随机数设置。只有元素内容可以进行“随机数设置”,因此如果您尝试在严格的 CSP 中使用 OPs 属性,则执行将失败。 - Bradley

13

试试像这样

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

if(script.readyState) {  //IE
script.onreadystatechange = function() {
  if ( script.readyState === "loaded" || script.readyState === "complete" ) {
    script.onreadystatechange = null;
    alert(jQuery);
  }
};
 } else{//others
script.onload = function() {
  alert(jQuery); 
}
}
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"
document.documentElement.appendChild(script);

4

我的回答是Jaykesh Patel 答案的延伸。我已经实现了这个代码,以便加载多个JavaScript。希望这能帮助到大家:

// RECURSIVE LOAD SCRIPTS
function load_scripts( urls, final_callback, index=0 )
{
    if( typeof urls[index+1] === "undefined" )
    {
        load_script( urls[index], final_callback );
    }
    else
    {
        load_script( urls[index], function() {
            load_scripts( urls, final_callback, index+1 );
        } );
    }
}

// LOAD SCRIPT
function load_script( url, callback )
{
    var script = document.createElement( "script" );
    script.type = "text/javascript";
    if(script.readyState) // IE
    {
        script.onreadystatechange = function()
        {
            if ( script.readyState === "loaded" || script.readyState === "complete" )
            {
                script.onreadystatechange = null;
                callback();
            }
        };
    }
    else // Others
    {  
        script.onload = function() { callback(); };
    }
    script.src = url;
    document.getElementsByTagName( "head" )[0].appendChild( script );
    debug("javascript included: "+url);
}

// EXAMPLE  
var main = function()
{
    console.log("main function executed");
}
var js = [ "path/to/script-1", "path/to/script-2", "path/to/script-3" ];
load_scripts( js, main );

4
实际上,你可以将 loadedContent() 放在你正在加载的脚本的最后一行(这是JSONP背后的概念)。

如果这不是你的脚本呢? - symbiont

1

这就是你所需要的一切

await new Promise((resolve) => {
    let script = document.createElement("script");

    script.onload = () => {
        resolve();
    };

    script.src = "https://example.net/app.js";

    document.head.appendChild(script);
});

-3
  $.getScript("your script",function () {
      "your action";
  });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接