【问题标题】:Execute function after layout re-render in Svelte在 Svelte 中重新渲染布局后执行功能
【发布时间】:2019-10-24 15:03:22
【问题描述】:

当我单击 Svelte 中的表格行时,我想创建一个弹出菜单。我使用document.querySelectorAll 方法为onMount 内的每个表格行添加了一个onclick 事件。在onMount 函数中,我还重新渲染了显示的表格。如何将 onclick 值应用于重新渲染的元素?

onMount(() => {
  console.log(document.querySelectorAll(".results .table table tbody tr"));
  /* -> returns array with only 1 element -> not correct */

  /* ... re-render logic here */
}

但是当我添加超时时:

onMount(() => {
  setTimeout(() => {
      console.log(document.querySelectorAll(".results .table table tbody tr"));
  }, 5000);
  /* -> returns array with all elements */

  /* ... re-render logic here again */
}

可以在here找到包含完整源代码的 REPL

【问题讨论】:

  • 您不需要为每一行添加点击事件。捕捉表格上的点击并使用目标来识别行。
  • 谢谢您的回答!确实,我可以对表格使用点击事件并选择目标,但是我会遇到其他问题。我会将 td 作为目标而不是行。我还必须检测我是否单击了表头或一行。我必须得到事件处理的行
  • 我知道您不需要 th 和 tr 点击。所以忽略它们。
  • 您能否重现您在REPL 中看到的问题?目前还不清楚发生了什么。一般来说,您不应该在 Svelte 应用程序的上下文中使用 document.querySelectorAll — 您正在混合和匹配范式(命令式与声明式),这通常不会很好地结束!
  • 感谢您的提示。我刚刚在我的问题中添加了 REPL 链接

标签: javascript svelte svelte-component


【解决方案1】:

我正在写一些想法,但是太长了,无法发表评论。

你在 Svelte 可以为你做的 REPL 中做了大量的额外工作。我同意@voscausa 的观点,即您应该将活动委托给table。您几乎不必在 Svelte 中使用 document.querySelector。您将遍历所有行两次。您的所有事件侦听器附件都应该是标记中的属性,而不是附加在 JS 中,也不附加在初始化函数中(因此事件委托到表中)。您一直在监控鼠标位置,但您只在onclick 中使用它,这是一个MouseEvent 并且可以访问X 和Y 数据。

将点击监听切换到容器:

<div class="results" on:click={handleClick}> ... </div>

<script>
  function handleClick(e) {
    const tr = e.target.closest('tr');
    const td = e.target.closest('td');
    if (td) {
      /* code */
    } else {
      /* code */
    }
  }
  </script>

如果您需要它出现在整个文档中,您可以使用&lt;svelte:window&gt; 而不是.results。

要更新 .option div 的 css,请执行以下操作:

<div class="options" style=`left:${optionsStyle.left}px;top:${optionsStyle.top}px`> ... </div>
<script>
  let optionsStyle = {left: 0, top: 0};

  function handleClick(e) {
    /* code */

    let left = 0, right = 0;
    /* calculate left and right here */
    optionsStyle  = {left: e.clientX, top: e.clientY};

    /* code */
  }
</script>

有关切换类,请参阅class directive。一个元素上可以有多个类指令。 (很明显,我还没有完成所有的逻辑。)

<div class="options" class:expand={optionsExpand}> ... </div>
<script>
  let optionsExpand = false;

  function handleClick(e) {
    const tr = e.target.closest('tr');
    const td = e.target.closest('td');
    if (td) {
      /* code */
      optionsExpand = true;
    } else {
      /* code */
      optionsExpand = false;
    }
  }
</script>

我个人会将选项弹出窗口变成它自己的组件,并将 optionsExpand 布尔值作为道具传递。

像我在这里描述的那样做事情会让你以 Svelte 思维方式思考,它会简化你的代码,你不需要超时,也不需要afterUpdates 函数。

【讨论】:

  • 感谢您的有用帖子!我会像你展示的那样重写代码。
猜你喜欢
  • 1970-01-01
  • 2016-06-29
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 2021-09-02
  • 1970-01-01
  • 2017-10-17
  • 2015-08-15
相关资源
最近更新 更多