如何使用 javascript 而不将其附加到 DOM

Ank*_*har 2 html javascript single-page-application

我正在从头开始开发一个单页应用程序(SPA)。我从头开始只使用 HTML、CSS 和普通 JavaScript,不使用任何外部框架。

我的应用程序最初将加载网页,但在导航到其他页面(例如page2)时,它只会从page2.js加载有关其他page2 的所需数据和功能,而不会重新加载整个网页。

为了使用 JavaScript,我将其附加到正文中。但问题是,当我再次导航同一页面时,它会再次附加相同的 JavaScript。我访问的页面越多,附加的脚本就越多。

我尝试删除现有的脚本标签以支持或即将推出的脚本,并且效果很好,但是有没有一种方法可以让我不必首先将脚本附加到 DOM?

所以我的问题是,有没有一种方法我们可以在不使用任何物理介质(DOM)的情况下解析(不仅仅是普通读取)或执行 JavaScript 文件

虽然我期待纯 JavaScript,但库也可以工作,只需要一个逻辑解释

T.J*_*der 5

所以我的问题是,有没有一种方法我们可以在不使用任何物理介质(DOM)的情况下解析(不仅仅是普通读取)或执行 JavaScript 文件

是的你可以。如何做到这一点取决于您要支持的环境的先进程度(无论是本机还是通过可以模拟旧环境中某些内容的工具)。

在现代环境...

...您可以使用动态导入来解决这个问题,这是 ES2020 中的新增功能(但已经受到最新浏览器的支持,并由 Webpack 和 Rollup.js 等工具模拟)。使用动态导入,您可以执行以下操作:

async function loadPage(moduleUrl) {
    const mod = await import(moduleUrl);
    mod.main();
}
Run Code Online (Sandbox Code Playgroud)

无论请求多少次,在一个领域内,模块只会加载一次。(您的 SPA 将在一个领域内,因此可以工作。)因此上面的代码将在第一次动态加载模块的代码,但只是在第二次、第三次等等时返回对已加载模块的引用。main将是您从模块导出的一个函数,告诉它您已经(返回)到“页面”。您的模块可能如下所示:

// ...code here that only runs once...
// ...perhaps it loads the markup via ajax...

export function main() {
    // ...this function gets called very time the user go (back) to our "page"
}
Run Code Online (Sandbox Code Playgroud)

CodeSandbox 上的实例。

在较旧的环境中...

...给你两个答案:

你可以用eval...

您可以使用 ajax 从服务器以文本形式读取代码,然后使用eval. 你会听到“eval是邪恶的”,这对它来说是一个不错的高层理解。:-) 反对它的论点是:

  1. 需要解析代码;有些人声称启动代码解析器是“慢”(对于“慢”的某些定义)。

  2. 它解析并评估字符串中的任意代码。

您可以明白为什么#2 特别可能有问题:您必须信任您正在评估的字符串。因此,切勿在其他用户的会话中使用eval用户提供的内容(用户 A 可能试图使用您在用户 B 的会话中运行的代码执行恶意操作)。

但就您而言,您想要并且需要这两件事,并且您信任字符串的来源(您的服务器),所以没关系。

但你可能不需要

不过,我认为即使在较旧的环境中也不需要这样做。您的代码已经知道需要为“页面”X 加载什么 JavaScript 文件,对吧?因此,只需查看该代码是否已加载,如果已加载,则不要再次加载。例如:

function loadPage(scriptUrl, markupUrl) {
    // ...
    if (!document.querySelector(`script[src="${scriptUrl}"]`)) {
        // ...not found, add a `script` tag for it...
    } else {
        // ...perhaps call a well-known function to run code that should run
        // when you return to the "page"
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您不想使用 DOM,可以使用一个对象 或Map或Set来跟踪已加载的内容。