ページリンククリック時に、ページコンテンツ読み込み前にJavaScriptを実行する方法は?

Hi.
When we change page in Discourse, these are the apparent steps:

  1. We click on the link
  2. The current content disappears and the loader appears
  3. The URL is updated and the new content appears

This is slightly different when we go from a page to the home, as the URL is changed to the home URL when the current content disappears, and not when the new content appears.

My goal is to have a script that is executed as soon as we click any page link on Discourse.
api.onPageChange won’t fit in this case since the code is executed quite at the same time the new page content is loaded.

Is there a Discourse method for that? I look at the event triggers but didn’t find any one corresponding to what I need.

「いいね!」 1

Hey :wave:

There’s currently no method in the Plugin-API that will allow you to fire a script before a page transition because this has not come up before as far as I recall.

That said, you can leverage on the willTransition() action in the application route

You would use something that like this in your theme / component

// this fires after the transition
api.onPageChange((url, title) => {
  console.log("after transition");
});

// this fires right before the transition
api.modifyClass("route:application", {
  pluginId: "some-name",
  actions: {
    willTransition() {
      // run core code first
      this._super(...arguments);
      // then do some work
      console.log("before transition");
      // you can also do something like this to see what data you have
      // to work with like _router
      console.log(this)
    }
  }
});

「いいね!」 6

Exactly what I needed. Thanks!

「いいね!」 2

これはトピックリストからトピックに入るときには発火しないようですね。

追加も試してみました。

      api.modifyClass("route:topic", {
        pluginId: PLUGIN_ID,
        actions: {
          willTransition() {

これも発火しません。

機能しない可能性のある理由をいくつか挙げます。

  1. アクションをハッシュに入れるのは古い構文で、Discourse ではもはや使用されていません。理論的には機能するはずですが、新しい構文との相互運用性が完璧ではない可能性があります。最新の方法は次のようになります。

    api.modifyClass("route:application", (Superclass) => class extends Superclass {
      @action
      willTransition() {
        console.log("何かをする");
        super.willTransition(...arguments);
      }
    });
    

    標準の modifyClass の免責事項が適用されます。これはリスクがあり、いつでも壊れる可能性があります。

  2. すべての場合において、willTransition がアプリケーションルートで確実にトリガーされるとは思いません。(例:子ルートに willTransition アクションがある場合、必ずしもバブルアップするとは限りません)

代わりに Ember ルーターサービスのイベントを使用することをお勧めします: RouterService | 5.12.0 | Ember API Documentation

例:

const router = api.container.lookup("service:router");
router.on("routeWillChange", () => {
  console.log("ルート変更前がトリガーされました");
});
「いいね!」 2

ありがとうございます、Davidさん。次回試してみます!

この調査は、ページ遷移時に何かを実行する方法が必要だった(えーと)ため、そしてレンダリングの前に実行する必要があったために開始されました。

ページ変更APIイベントは、ページ要素がレンダリングされる前に確実に発生するとは限らないようです。

「いいね!」 1

これを完璧に行うのは難しいと思います。Ember はレンダリングを完全に制御することを期待しているため、任意のポイントにフックしようとすると困難であり、問題が発生する可能性があります(何を行おうとしているかによります)。

もちろん、あなたの最終的な目標が何であるかはわかりません…したがって、苦労する価値があるのかもしれません。その場合は、私を無視していただいて構いません :wink:

(もちろん、解決しようとしている問題について Dev トピックを開いていただければ、喜んで確認します)

コードはオープンソースなので、明示的に説明させていただきます。

サードパーティの広告プロバイダーと連携しており、新しいページの広告がトリガーされる前に実行する必要がある JavaScript の広告ページリセット機能があります。

改善点は歓迎します。すでに Johani のコードを使用してトピックリストでこれを実現しました。(オープンな PR で)。

しかし、これによりトピックが残ってしまいました。次にあなたの提案を試して、さらに改善されるようであれば両方のインスタンスに採用します。

なるほど、DOMを直接変更しているわけではないのですね :ok_hand:

その場合、routeWillChange が機能することを願っています。次のルートがレンダリングされる前に確実に発火するはずです。

注意点としては… リダイレクトのようなケースでは、2回発火する可能性があります。あるいは発火しても、遷移が最終的に中止されることもあります。しかし、このケースでは問題ないかもしれません。

「いいね!」 2

はい、メアフィールド・テクノロジー・タワーズでは、そのような不正な直接DOM操作は一切行っていません。:sweat_smile:

はい、サービスを利用します。それが目的ですから!結果は他の人も興味を持つかもしれないので、経験を報告します。

「いいね!」 3

はい、これで整理され、両方のルートで正しい順序で処理が行われるようになりました。

:rocket:

ご協力ありがとうございました!

「いいね!」 2