【问题标题】:Prevent DOM reuse within lit-html/lit-element防止在 lit-html/lit-element 中重用 DOM
【发布时间】:2021-04-10 19:27:22
【问题描述】:

我正在寻找一种不在 lit-html/lit-element 中重用 DOM 元素的方法(是的,我知道,我正在关闭其中一个主要功能)。特定场景是将现有系统移动到 lit-element/lit-html,该系统在某些点嵌入了 trumbowyg WYSIWYG 编辑器。这个编辑器将自己附加到一个在 lit-element 中创建的 <div> 标签并修改它自己的内部 DOM,但当然 lit-html 不知道这已经发生了,所以它经常会重用相同的 <div> 标签而不是创建一个新的。我正在寻找类似于 vue.js 键属性的东西(例如,preventing Vue from aggresively reusing dom-elements

我觉得lit-html 中的live() 指令应该对此有用,但是它可以防止基于给定属性的重用,即使所有属性都相同,我也想防止重用。谢谢!

【问题讨论】:

  • 我认为只要提到的 div 不受任何观察属性的影响,它不应该被重新渲染并保留您手动对其所做的任何更改,如果您可以提供一些最小的复制您的问题,我们可以查看您的情况可能导致重新渲染的原因
  • 作为一个关于相互交织的单独问题的说明——将 Popper 与 Bootstrap 一起使用,我发现删除 update(changedProperties) 中带有 $().popper('destroy') 的所有 poppers 很有帮助,然后将它们重新添加到 @ 987654329@ 保持更新时的 DOM 与 lit-html 认为的 DOM 同步。

标签: custom-element lit-element lit-html trumbowyg


【解决方案1】:

我在富文本编辑器和 contenteditable 上遇到过类似的问题 - 由于模板如何更新 DOM,您不希望它成为模板的一部分。

您可以通过在非 Lit DOM 中添加一个新元素,然后将 that 添加到 Lit 管理的 DOM 中:

class TrumbowygEditor
  extends HTMLElement {

  constructor() {
    super();
    const shadow = this.attachShadow({mode: 'open'});
    const div = document.createElement('div');
    shadow.appendChild(div);
    
    const style = document.createElement('style');
    // Add CSS required 
    shadow.appendChild(style);

    $(div).trumbowyg(); //init
  }
}

customElements.define('trumbowyg-editor', TrumbowygEditor);

由于这是在自定义元素的阴影 DOM 中运行,因此 Lit 不会触摸它,您可以这样做:

html`
    <div>Lit managed DOM</div>
    <trumbowyg-editor></trumbowyg-editor>`;

但是,您必须在 TrumbowygEditor 上实现属性和事件,以添加您想要传递到嵌套 jQuery 组件或从嵌套 jQuery 组件获取的所有内容。

如果您可以获得 jQuery/Trumbowyg 的模块版本(或您的构建工具支持),您可以使用 import 添加脚本,或者您可以将 &lt;script&gt; 标签添加到您的组件,在 @ 添加后备加载 DOM 内容987654327@,然后在&lt;script&gt;的加载事件上调用$(div).trumbowyg()来初始化组件。

虽然更麻烦,工作量更大,但我推荐后者,因为这两个组件都很大,而且(感谢 jQuery 建立在现在已经 15 年的假设之上)需要同步加载(&lt;script async&lt;script defer 不要工作)。尤其是在较慢的连接上,Lit 会在 jQuery/Trumbowyg 加载之前很久就准备好了,所以你希望 &lt;trumbowyg-editor&gt; 在发生这种情况时看起来不错(显示微调器、在适当的空间中布局等)。

【讨论】:

    【解决方案2】:

    您写道,您将外部库直接附加到由 lit-html 管理的元素。听起来你基本上是在这样做:

    render(html`<section><div id=target></div></section>`, document.body)
    external_lib.render_to(document.querySelector("#target"))
    

    如果您这样做,请尝试创建自己的 div,让外部 lib 渲染到该 div,最后将该 div 附加到 lit-html:

    let target_div = document.createElement('div')
    render(html`<section>${div}</section>`, document.body)
    external_lib.render_to(target_div)
    

    【讨论】:

    • 这适用于很多场景,但是使用 DOM 重用,如果 lit-element/lit-html 不知道 target_div 已被更改,它可以重用
      DOM 用于不相关的内容时页面更改,其内容现在与实际内容不同步。这是我使用的导致问题的策略。
    猜你喜欢
    • 2022-09-13
    • 2021-01-01
    • 2021-08-01
    • 1970-01-01
    • 2019-10-24
    • 2021-05-23
    • 1970-01-01
    • 2021-07-29
    • 2019-08-05
    相关资源
    最近更新 更多