在您的网页上加载脚本

2025-06-09

在您的网页上加载脚本

我错过了火车,还有一个小时的时间,所以让我们来讨论一些简单的事情,在网页上加载脚本。

捆绑销售

强制加载所有脚本的一个超级简单的方法是将它们全部打包成一个文件。然而,这种方法代价高昂(愚蠢),因为你不能只导入你需要的脚本。

作为脚本文档

当我们还是小鸭子时,我们就被教导将脚本放在文档中,因为它们会在加载网页时立即加载。

<html>
    <head>
        <title></title>
        <script src="main.js"></script>
        <script src="util.js"></script>
        <script src="events.js"></script>
        <script src="speech.js"></script>
    </head>
    <body>
    <h1>Page Title</h1>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

文档中的脚本元素无法访问在脚本之后声明的 HTML 元素,因为在加载脚本时,目标元素尚不存在。换句话说,在上面的例子中,你无法main.js访问h1元素。这就是为什么小鸭子们常常希望他们的脚本在页面其余部分加载完成后再加载。

作为正文末尾的脚本

如果您想在文档加载后执行脚本,只需将它们放在正文末尾即可。
这样做在某些时候已成为一种常见做法,因为它可以加快页面加载速度。这意味着页面图片和样式表已经加载完毕。脚本标签不会阻止/延迟它们。这对用户来说更方便。

<html>
    <head>
        <title></title>
    </head>
    <body>
    <h1>Page Title</h1>
    <script src="main.js"></script>
    <script src="util.js"></script>
    <script src="events.js"></script>
    <script src="speech.js"></script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

完全可以通过页面头部声明的脚本访问页面上的元素,但您必须等待页面加载完成的事件。过去,人们会为页面主体分配一个onload 属性。

<body onload="method()"></body>
Enter fullscreen mode Exit fullscreen mode

使用 jQuery

每个人都知道以下内容。

$(document).ready(function() {
  // the page has finished loading
}
Enter fullscreen mode Exit fullscreen mode

香草

几乎与上面的相同,但没有 jQuery。

document.addEventListener('DOMContentLoaded', event => {
  // the page has finished loading
})
Enter fullscreen mode Exit fullscreen mode

通过编程注入

你可以通过在脑袋里注入脚本来模仿某种 require 函数。这其实并没有听起来那么可怕。

function importScript(src) {
    let script = document.createElement('script')
    script.setAttribute('src', src)
    document.head.appendChild(script)
}

importScript('main.js')
importScript('util.js')
importScript('events.js')
importScript('speech.js')
Enter fullscreen mode Exit fullscreen mode

使用异步函数

有些人坚持将多个承诺包装到异步函数中。

// imagine the same import function but one that implements a Promise.
document.addEventListener('DOMContentLoaded', async event => {
  window.main = await importScript('main.js')
  window.util= await importScript('util.js')
  window.events= await importScript('events.js')
  window.speech = await importScript('speech.js')
}
Enter fullscreen mode Exit fullscreen mode

作为模块

现在已经是 2018 年了,鸭子已经变成了天鹅,我们可以通过 script 标签中的额外属性来导入模块。函数式程序员对此非常热衷,这可能是它传播到 Node 的原因。

<script type="module">
  import * as util from './util.js'
  util.default()
  util.extra()
</script>
Enter fullscreen mode Exit fullscreen mode
<script type="module">
  import { display, extra } from './main.js' // that too
  display.message()
  extra()
</script>
Enter fullscreen mode Exit fullscreen mode

我有个朋友问我,为什么 Node 不直接用 export 呢?因为 Node 的出现比 export 关键字出现的时间要早​​得多。:P

以函数形式使用的 import 关键字可以实现动态导入。它返回一个 Promise 对象,该对象负责解析脚本导出的内容。像这样使用 import不需要在脚本标签中添加type ="module"属性。

import('./util').then(module => window.util = module).catch(console.error)
Enter fullscreen mode Exit fullscreen mode

因为 import 做出了承诺所以只要我们的事件处理函数是异步的,我们就可以在DOMContentLoaded事件中等待它。

document.addEventListener('DOMContentLoaded', async event => {
    window.util = await import('./util')
})
Enter fullscreen mode Exit fullscreen mode

要加载多个脚本,只需迭代一个数组

出于某些原因,你可能希望解析器函数通过标识符(而非完整路径)导入脚本,为什么不直接使用上下文对象呢?在本例中,上下文对象默认为窗口。你看到的虽然不太理想,但你明白我的意思。

let libs = ['main', 'utils', 'session']
const init = async (context = window) => libs.forEach(async lib => context[lib] = await import(init.resolve(lib)))
init.resolve = lib => `./js/${lib}.js`


init(window) // libs are now properties of window
init({}) // initialize on empty object
init({
    utils: 'abc'
}) // utils is overwritten
Enter fullscreen mode Exit fullscreen mode

使用RequireJS

我个人一直不明白为什么有人会认为这就是他们生活中需要的东西。它从来没有帮我解决过任何问题。然而,鉴于它的名声,它必须被纳入。

requirejs(["util"], util => {
    //This function is called when util.js is loaded.
    window.util = util
})
Enter fullscreen mode Exit fullscreen mode

获得

这是requirejs简化版,它会在包含模块标识符的上下文中评估 XMLHttpRequest 的响应文本。当时还没有fetch 函数,也没有模块脚本或 import/export 关键字。Acquire 只需一个函数调用即可同时支持同步和异步操作,但同步 XMLHttpRequest 或许是最不推荐的做法了。

如果您喜欢这篇文章,请经常访问 dev.to

鏂囩珷鏉ユ簮锛�https://dev.to/jochemstoel/loading-scripts-on-your-webpage-576c
PREV
为 Node 和浏览器编写自己的可链接事件发射器类
NEXT
第 005 集 - 依赖注入 - ASP.NET Core:从零到过度