繁体   English   中英

如何在 Svelte/Sapper 中加载外部 JS 库?

[英]How do I load an external JS library in Svelte/Sapper?

我一直在尝试将 ace 编辑器 ( https://ace.c9.io/ ) 加载到我的 Sapper 应用程序中。 当我在 Sapper 路由中加载它时,我成功地将它加载到脚本标签中,但是当我尝试在 Svelte 组件中执行相同操作时,该组件再次由路由呈现,我收到错误消息:

ace 未定义

这是我的代码,如果它是 Sapper 路由,它可以正常工作:

<div id="editor"> def main():
    return sum(range(1,100))
</div>

    <script src="https://pagecdn.io/lib/ace/1.4.6/ace.js" type="text/javascript" charset="utf-8"></script>

    <script>
          var editor = ace.edit("editor");
          editor.setTheme("ace/theme/monokai");
          editor.session.setMode("ace/mode/python");
          editor.resize()
    </script>

当我第一次开始使用 Svelte2 时,我编写了一个组件来加载外部遗留 JS 库,然后将其重构为 Svelte 3。

// LibLoader.svelte

<svelte:head>
  <script bind:this={script} src={url} />
</svelte:head>

<script>
  import { onMount, createEventDispatcher } from 'svelte';

  const dispatch = createEventDispatcher();
  export let url;
  let script;

  onMount(async () => {
    script.addEventListener('load', () => {
      dispatch('loaded');
    })

    script.addEventListener('error', (event) => {
      console.error("something went wrong", event);
      dispatch('error');
    });
  });
</script>
// MyComponent.svelte

<LibLoader url="myExternalLib.js"
on:loaded="{onLoaded}" />


<script>
  import LibLoader from './LibLoader.svelte';


  function onLoaded() {
    myExternalLib.doStuff();
  }
</script>

这没有经过彻底测试,一次性使用可能不需要单独的组件; 但基本上这种方法解决了 Rich Harris 提到的时间问题。 如果可以的话,现在import显然是更好的选择。

在 Svelte 中使用外部库的方法是import它。 我不知道它是多么容易做到这一点与王牌-代码编辑器往往是有些复杂,一个读取语言和主题等自己的模块系统-但在理论上它会是这个样子:

<script>
  import ace from 'ace';
  import { onMount } from 'svelte';

  let div;
  let editor;

  onMount(() => {
    // we need to use onMount because the div hasn't
    // been created by the time the init code runs
    editor = ace.edit(div);
    editor.setTheme("ace/theme/monokai");
    editor.session.setMode("ace/mode/python");
    editor.resize();

    return () => {
      // any cleanup code goes here
    };
  });
</script>

<div bind:this={div}> def main():
    return sum(range(1,100))
</div>

如果导入失败,你总是可以用老式的方式来做,将<script src="...">标签添加到你的主template.html ,并继续使用ace作为全局。 Svelte 组件内的<script src="...">标签将异步加载 — 换句话说,您的组件代码通常会在外部脚本加载之前运行。

我需要添加Keycloak Javascript 适配器 这里的旧答案( https://stackoverflow.com/a/61979865/2013924 )对我不起作用,所以我只是

  1. 首先将 Keycloak 脚本包含在<head>内的template.html例如<script src="http://localhost:8080/auth/js/keycloak.js"></script>
  2. 然后在我的login.svelte路由中使用了onMount

在组件第一次渲染到 DOM 之后运行

完全按预期工作。

// document.js

export function loadScript(src) {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = src;

        document.body.appendChild(script);

        script.addEventListener('load', () => resolve(script));
        script.addEventListener('error', () => reject(script));
    });
}

然后在苗条的组件上

// index.svelte
<script>
    import { onMount } from 'svelte';
    import { loadScript } from './document.js';

    onMount(async () => {
      await loadScript('your-external-script.js');
      console.log('script loaded successfully!');
    };
</script>
{@html '<script src="/js/pages/projects.js" />'}

也可以用于 SvelteKit。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM