在点击任何页面链接时触发 JavaScript,但在页面内容加载之前

你好。
在 Discourse 中切换页面时,大致会经历以下步骤:

  1. 点击链接
  2. 当前内容消失,加载器出现
  3. URL 更新,新内容出现

不过,从任意页面回到首页时略有不同:URL 会在当前内容消失时即切换为首页 URL,而不是在新内容加载完成后才更新。

我的目标是编写一个脚本,使其在点击 Discourse 中的任意页面链接时立即执行。
api.onPageChange 并不适用,因为该代码执行的时间点与新页面内容加载几乎同步。

Discourse 是否有对应的方法?我查看了事件触发机制,但尚未找到符合我需求的触发器。

1 个赞

:wave:

目前 Plugin-API 中没有允许您在页面过渡之前触发脚本的方法,据我所知,此前并未出现过此类需求。

不过,您可以利用应用程序路由中的 willTransition() 操作:

您可以在主题/组件中使用类似以下内容:

// 此操作在过渡后触发
api.onPageChange((url, title) => {
  console.log("after transition");
});

// 此操作在过渡前立即触发
api.modifyClass("route:application", {
  pluginId: "some-name",
  actions: {
    willTransition() {
      // 先运行核心代码
      this._super(...arguments);
      // 然后执行一些操作
      console.log("before transition");
      // 您也可以像这样查看您拥有的数据,例如 _router
      console.log(this)
    }
  }
});
6 个赞

这正是我需要的。谢谢!

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("route will change 已触发");
});
2 个赞

太好了,谢谢你,David,我下次会试试!

这次调查(咳咳)是因为我需要一种在每次页面更改时触发某些操作的方法,而且是在渲染(Render)之前

Apparently,页面更改 API 事件似乎不能保证在页面元素渲染之前触发。

1 个赞

我认为您将很难完美地做到这一点。Ember 希望完全控制渲染,因此尝试挂钩到任意点将很困难,并且可能会导致问题(取决于您要尝试做什么)。

显然,我不知道您的最终目标是什么……所以也许这种痛苦是值得的。如果是这样:请随时忽略我 :wink:

(当然,如果您想就您试图解决的问题开设一个 Dev 主题,我很乐意看看)

很高兴能明确说明,因为代码是开源的:

我正在与第三方广告提供商合作,他们有一个 JavaScript 中的广告页面重置函数,需要在触发新页面的广告之前运行。

任何改进都受欢迎,并且我已经通过 Johani 的代码在主题列表中实现了这一点。(在一个开放的 PR 中)。

但这遗留了主题……我接下来会尝试你的建议,如果能进一步改进,我将在两个实例中都采用它。

我明白了,所以你不是直接修改 DOM :ok_hand:

那样的话,我希望 routeWillChange 会起作用——它应该在下一个路由渲染之前触发。

需要注意的是……在重定向的情况下,它可能会触发两次。或者触发后,但转换最终被中止了。但也许在这种情况下是可以的。

2 个赞

是的,在 Merefield Technology Towers 这里没有任何不好的直接 DOM 修改的胡闹。:sweat_smile:

是的,我会使用该服务,它的用途就是如此!我会反馈我的经验,因为我相信结果可能会让其他人感兴趣。

3 个赞

是的,这样就清理干净了,现在两条路线上的事情都按正确的顺序进行了。

:rocket:

感谢您的帮助!

2 个赞