Svelte 动态 html 元素未应用 css

Svelte dynamic html elements do not have css applied

我有一个使用库显示 JSON 树的 svelte 组件,但该库需要一个 html 挂钩才能加载。之后它会生成自己的 html 结构以及自己的 classes 和 id。到目前为止一切顺利,但如果我在我的组件中为将来生成的选择器添加一些样式,则不会应用该样式。

这是问题所在吗?有一些解决办法吗?

这是我的代码示例:

<script>
  import { onMount } from "svelte";
  import { Content } from "@smui/card";
  import { copyToClipboard } from "../../public/js/utils";

  export let data;
  let contentBody;

  onMount(() => {

    const editor = new JSONEditor(
      contentBody,
      { mode: "view", navigationBar: false },
      data
    );

    const editorMenu = document.getElementsByClassName("jsoneditor-menu")[0];
    const copy = document.createElement("img");
    copy.src = "../../public/img/copy.png";
    copy.setAttribute("class", "custom-button");
    editorMenu.append(copy);

    copy.onclick = () => copyToClipboard(editor.getText()));
  });
</script>

<style>
  .jsoneditor-menu {
    background-color: #525b69;
    border: 1px solid #e8e8e8;
  }

  .jsoneditor {
    border: 1px solid #e8e8e8;
  }

  .json {
    height: 555px;
  }

 .custom-button {
    width: 20px;
    height: 20px;
    margin: 2px;
    padding: 2px;
    border-radius: 2px;
    border: 1px solid transparent;
    color: #fff;
    opacity: 0.8;
    font-family: arial, sans-serif;
    font-size: 10pt;
    float: left;
  }

</style>

<Content>
  <div class="json" bind:this={contentBody} />
</Content>

注意:该样式仅适用于根元素 json class

是的,您已正确识别问题。解决方案是使用 :global 魔术伪选择器 (docs) 使您的样式全局化。

<style>
  /* this will not be removed, and not scoped to the component */
  :global(.foo) { ... }

  /* this will not be removed, but still scoped to divs inside _this_ component */
  div :global(.bar) { ... }
</style>
Svelte 中的

CSS 范围是通过在您编写的 CSS 选择器中添加一个唯一的 class 来实现的。比如你写.foo,编译器会把它变成.svelte-a3bmb2.foo.

为此,编译器还需要将此 class 添加到与选择器 .foo 匹配的所有元素。它可以针对它在标记中看到的元素执行此操作。但是对于运行时动态创建的元素就不行了。

这就是为什么(我猜)Svelte 会删除 CSS 与组件标记中的任何内容都不匹配的规则。编译器通常会在执行此操作时发出警告,例如 "unused CSS selector".

如果您将样式设置为全局样式,编译器就不再需要限定它们的范围,所以问题就解决了。