在Svelte中重新渲染布局后执行功能

时间:2019-10-20 14:03:47

标签: javascript svelte svelte-component

当我在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 */
}

可以找到具有完整源代码的REPL here

1 个答案:

答案 0 :(得分:1)

我在写一些想法,但是评论太久了。

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

将点击侦听器切换到容器:

MouseEvent

如果需要将其包含在整个文档中,则可以使用<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> 代替<svelte:window>

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

.option

有关切换类,请参见class directive。一个元素上可以有多个类指令。 (显然,我并没有完成所有逻辑。)

<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>

我个人会将“选项”弹出窗口变成其自己的组件,并传递<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函数。 / p>