Stimulus JS中处理集合中元素外点击的模式

3
我刚接触 stimulus,并试图找到正确的模式。我有一组表单项,默认情况下有一个隐藏的提交按钮。当您点击输入时,提交按钮会显示出来。
当您点击其他输入时,先前活动的提交按钮消失,新的提交按钮出现。如果您在所有输入之外点击,则有一个全局的 data-action="click@window->editor#hideButton",用于隐藏提交按钮。
如果您运行代码片段,它具有我要实现的完全 UX。但是,将全局窗口事件附加到控制器的每个实例似乎过于复杂。此外,每次页面上发生其他操作的点击时都会触发此全局点击。
这种模式在模态上下文中有效,但在我的集合示例中感觉不对。在我的示例中,每次点击都会调用 4 次 hideButton 函数。即使与页面上的其他元素交互也是如此。 https://discuss.hotwired.dev/t/best-practices-for-handling-clicks-outside-element/1266 我已经阅读了为集合中的每个项目创建控制器是正确的方法。

在刺激措施方面,依靠这一全球事件是正确的方法吗?或者,我应该重新思考整个方法以实现用户体验(意识到我的架构可能有很大偏差)。

const application = Stimulus.Application.start()

application.register("editor", class extends Stimulus.Controller {
  static targets = ["button"]
  showButton() {
    this.buttonTarget.classList.remove("hide")
  }
  hideButton() {
    if (this.element === event.target || this.element.contains(event.target)) return;

    this.buttonTarget.classList.add("hide")
  }
})
.hide {
  display: none;
}

li {
  margin: 10px;
  background: gray;
  width: 230px;
}

input:hover {
  cursor: pointer;
}

ul {
  list-style: none;
}
<script src="https://unpkg.com/stimulus@2.0.0/dist/stimulus.umd.js"></script>
<ul>
  <li data-controller="editor" data-action="click@window->editor#hideButton">
    <form>
      <label>Item1</label><br>
      <input type="text" data-action="click->editor#showButton">
      <input class="hide" type="submit" value="Submit" data-editor-target="button">
    </form>
  </li>
  <li data-controller="editor" data-action="click@window->editor#hideButton">
    <form>
      <label >Item2</label><br>
      <input type="text" data-action="click->editor#showButton">
      <input class="hide" type="submit" value="Submit" data-editor-target="button">
    </form>
  </li>
  <li data-controller="editor" data-action="click@window->editor#hideButton">
    <form>
      <label>Item4</label><br>
      <input type="text" data-action="click->editor#showButton">
      <input class="hide" type="submit" value="Submit" data-editor-target="button">
    </form>
  </li>
  <li data-controller="editor" data-action="click@window->editor#hideButton">
    <form>
      <label>Item4</label><br>
      <input type="text" data-action="click->editor#showButton">
      <input class="hide" type="submit" value="Submit" data-editor-target="button">
    </form>
  </li>
</ul>

1个回答

4

选项 1 - 仅使用 CSS 解决方案

如果可能的话,最好利用纯 CSS 的解决方案,这样会更高效、更易管理,并提供更易于访问的用户界面(如下所示)。

您可以使用 :focus-within CSS 伪选择器来实现相同的目标。

这使您可以利用 CSS 特性比如 opacity 来实现过渡效果。


.form li [type='submit'] {
  opacity: 0;
  transition: opacity 300ms ease-in-out;
}

.form li:hover [type='submit'],
.form li:focus-within [type='submit'] {
  opacity: 1;
}

选项2-使用 focusin focusout 事件

不过,如果您必须使用JavaScript,则建议避免全局点击和输入点击,并改用 focusinfocusout 事件。

这些事件可以从侦听器(动作)所在的容器内的任何输入中冒泡,这意味着您可以在li内拥有任何类型的可聚焦元素,而无需注册单个单击操作。

您还应考虑此行为对仅使用键盘和移动设备的用户的影响,因此在下面的示例代码中使用了setTimeout

我还在下面的示例代码中利用了Stimulus的CSS类功能,但您不需要这样做。

<ul>
  <li
    data-controller="editor"
    data-action="focusin->editor#showButton focusout->editor#hideButton"
    data-editor-hidden-class="is-hidden"
  >
    <label>Item1</label><br />
    <input type="text" />
    <input
      class="is-hidden"
      type="submit"
      value="Submit"
      data-editor-target="button"
    />
  </li>
  <li
    data-controller="editor"
    data-action="focusin->editor#showButton focusout->editor#hideButton"
    data-editor-hidden-class="is-hidden"
  >
    <label>Item2</label><br />
    <input type="text" />
    <input
      class="is-hidden"
      type="submit"
      value="Submit"
      data-editor-target="button"
    />
  </li>
</ul>

import { Controller } from '@hotwired/stimulus';

class Editor extends Controller {
  static classes = ['hidden'];
  static targets = ['button'];

  showButton() {
    // ensure focus can 'move' to next target in container (e.g. press 'tab')
    setTimeout(() => this.buttonTarget.classList.remove(this.hiddenClass));
  }

  hideButton() {
    // ensure focus can 'move' to next target in container (e.g. press 'tab')
    setTimeout(() => this.buttonTarget.classList.add(this.hiddenClass));
  }
}

export default Editor;

感谢您的 CSS 建议。LB Ben Johnston。我会尝试使用焦点 JS 方法,以确保它实现了我所寻找的 UX 模式。 - computer_smile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接