在另一个控制器中刺激访问操作

rct*_*eil 5 javascript stimulusjs

这是我的刺激控制器之一:

import { Controller } from "@hotwired/stimulus"
import InfiniteScroll from 'infinite-scroll'

export default class extends Controller {
    static get targets() {
        return ["next", "grid", "footer", "infinitescrollelement"]
    }

    connect() {
        let infScroll;

        if (this.hasNextTarget) {
            infScroll = new InfiniteScroll(this.gridTarget, {
                path: '.next_page a',
                append: '[data-infinitescroll-target="infinitescrollelement"]',
                // append: `.${this.data.get("object")}-top-level`,
                scrollThreshold: false,
                status: '.page-load-status',
                button: '.view-more-button'
            })

            this.footerTarget.querySelector('.view-more-button').style.display = 'inline-flex'
        } else {
            this.footerTarget.querySelector('.view-more-button').style.display = 'none'
        }

        // When new content is appended, re-layout the gallery to ensure new photos position correctly
        ***infScroll.on('append', (event, response, path, items) => {
            ***layoutGallery(galleryElement)
        ***})
    }
}
Run Code Online (Sandbox Code Playgroud)

以 *** 开头的三行是我的问题所在。

基本上,当无限滚动附加新内容时,我需要在图库控制器中运行一个操作。我怎样才能做到这一点?它不能同时运行,只能在调用无限滚动事件时运行。

有任何想法吗?

LB *_*ton 7

根据 Stimulus 文档,跨控制器通信的推荐方式是通过浏览器事件

关于这件事有几点需要注意

  • jQuery 事件不是浏览器事件,默认情况下不会被 Stimulus 事件或任何非 jQuery 事件侦听器拾取(从代码的外观来看,我假设无限滚动是 jQuery 实用程序)
  • Stimulus 控制器有一个方便的方法this.dispatch可以轻松地分派事件,这些事件只是CustomEvent的一个薄包装。

从 HTML 开始

  • 从 HTMl 开始,我们可以使用 Stimulus 的事件侦听器功能,称为actions.
  • data-action="infinite-scroll:append->gallery#updateLayout"-> 这表示画廊控制器应该监听事件'infinite-scroll:append'并调用画廊的updateLayout方法(我只是编了这个名字,你想叫什么就叫什么)。
<main>
  <h1>Gallery with infinite scroll</h1>
  <section
    class="gallery"
    data-controller="gallery"
    data-action="infinite-scroll:append->gallery#updateLayout"
  >
    <div
      class="scroll-container"
      data-controller="infinite-scroll"
      data-infinite-scroll-target="grid"
    >
      <img src="/image-1" />
      <img src="/image-2" />
      <img src="/image-3" />
      <img src="/image-4" />
    </div>
  </section>
</main>
Run Code Online (Sandbox Code Playgroud)

从 jQuery 事件“append”触发非 jQuery 事件

  • 在下面更新的控制器代码中,我们首先检查是否infScroll存在,然后通过infScroll.on('append',....
  • 在这里,我们使用我们给this.dispatch它的名称触发一个真正的浏览器事件,该名称'append'将由控制器名称自动添加前缀(感谢 Stimulus!),因此实际事件将是'infinite-scroll:append',假设您的控制器注册为“无限滚动”。
  • 我们通过对象传递侦听器可能需要的所有内容detail,我们还添加cancelable: false,虽然这并不重要,但最好清楚这一点,并且刺激事件调度中的默认值是true
  • 请注意,我们还传递了event从 jQuery 侦听器获取的事件,这可能不是必需的,但最好知道该事件和将分派的事件是不同的事件。
  • 请注意,我们正在将target选项添加到this.dispatch,这不是必需的,但它确实使我们更清楚我们正在谈论哪个 DOM 元素。
  • 默认情况下,事件this.dispatch会冒泡,因此它们将被父元素拾取。
import { Controller } from '@hotwired/stimulus';
import InfiniteScroll from 'infinite-scroll';

class InfiniteScrollController extends Controller {
  static get targets() {
    return ['next', 'grid', 'footer', 'item'];
  }

  connect() {
    let infScroll;

    if (this.hasNextTarget) {
      infScroll = new InfiniteScroll(this.gridTarget, {
        path: '.next_page a',
        append: '[data-infinite-scroll-target="item"]',
        // append: `.${this.data.get("object")}-top-level`,
        scrollThreshold: false,
        status: '.page-load-status',
        button: '.view-more-button',
      });

      this.footerTarget.querySelector('.view-more-button').style.display =
        'inline-flex';
    } else {
      this.footerTarget.querySelector('.view-more-button').style.display =
        'none';
    }

    // When new content is appended, re-layout the gallery to ensure new photos position correctly
    if (infScroll) {
      infScroll.on('append', (event, response, path, items) => {
        // note: the 'event' here is the jQuery event, the dispatch below will also dispatch with its own event
        // passing the original jQuery event (which is not strictly a DOM event) in the detail as it may be used

        const detail = { event, response, path, items };

        this.dispatch('append', {
          cancelable: false,
          detail,
          target: event.target,
        });
      });
    }
  }
}

export default InfiniteScrollController;
Run Code Online (Sandbox Code Playgroud)