路由更改后重新评估标题中的小部件,无错误

我正在尝试覆盖此小部件模板:

      api.reopenWidget("header-contents", {
        template: hbs`

          {{#if this.site.desktopView}}
            {{#if attrs.sidebarEnabled}}
              {{sidebar-toggle attrs=attrs}}
            {{/if}}
          {{/if}}

          {{home-logo attrs=attrs}}

          {{#if attrs.topic}}
            {{header-topic-info attrs=attrs}}
          {{else if this.siteSettings.bootstrap_mode_enabled}}
            {{#if transformed.showBootstrapMode}}
              {{header-bootstrap-mode attrs=attrs}}
            {{/if}}
          {{/if}}

          <div class="panel clearfix" role="navigation">{{yield}}</div>
        `,
      });

尽管该模板目前与 discourse/app/assets/javascripts/discourse/app/widgets/header-contents.js at 4aa81e709ea49e30383a3a3acd33dfedaebfc240 · discourse/discourse · GitHub 中的原始模板 完全相同

它正在生成一个错误:

这出乎意料,尤其是我实际上并没有“更改任何内容”(目前)?

即使这是 唯一的 修改,我也能够重现此问题。

最终,我尝试更改此设置的原因是为了强制重新评估此模板,即使我没有进入或退出主题路由。

最终,我想添加逻辑,以便在进入和退出类别路由时强制刷新小部件,因为我的类别路由演示需要有所不同。

因此,这的一种解决方案可能是另一种强制刷新标题内容的方法。

无论如何,这似乎并没有按我应有的预期运行?

我们不想在这里投入太多时间——小部件不会存在太久了。您想进行什么自定义?我们是否可以通过在某处添加插件出口来提供帮助(我们现在有能力在小部件代码内部添加常规插件出口)。

您能否分享更多您的文件(例如,hbs 是从哪里导入的?)

1 个赞

这是哪个版本的 Discourse?site-header.js:337 目前没有引用“header”变量

1 个赞

好的。

import { hbs } from "ember-cli-htmlbars";

实际上,我试图根据路由切换 logo。在实际操作中,我通过在某些路由上为首页 logo 添加一个图片并覆盖主 logo 来实现。我希望在路由之间切换时重新评估该逻辑,这似乎在进入和退出 Topic 路由时有效,我猜是因为附加了所有内容的 header-contents 小部件具有评估 attrs.topic 的逻辑,而这显然会在发生时发生变化。

我的 category-logo-widget 附加方式如下:

      api.decorateWidget("home-logo:after", (helper) => {
        const currentPath = helper.register
          .lookup("service:router")
          .get("_router.currentPath");

        if (
          helper.widget.currentUser &&
          !helper.widget.site.mobileView &&
          currentPath.indexOf("discovery") === -1
        ) {
          return helper.attach("category-logo-widget");
        }
      });

这可以正常工作,但它不会在某些路由转换之间重新评估,因此无法完全动态地满足要求,而无需重新加载页面。

哎呀,这可能是问题所在,我感觉可能是这样,但我的测试显然太肤浅了,无法排除它。

我看到了这个提交,我需要更新我的开发实例…… PERF: Memoize element references for `dockCheck` (#21079) · discourse/discourse@db16700 · GitHub

无论如何我都会回滚,感谢你的时间!

这很可能是问题所在。Widget ‘templates’ 是 Discourse 的自定义内容,其编译方式与 Ember templates 完全不同。你需要像这样导入 hbs

看起来我们有一个 site-header:force-refresh appEvent,你可以在响应其他 appEvent 或 Ember 路由事件时触发它:

(示例触发器在此处 here

3 个赞

太棒了,谢谢你,David。我会修复过时的安装,并在此尝试你的建议。堆积如山的问题,谢谢你帮忙理清!

3 个赞

所以可能有点多余,但我最终使用了你的建议,其中包含:

      api.onPageChange(url =>  {
        const applicationController = container.lookup(
          "controller:application"
        );
        applicationController.appEvents.trigger(
          "site-header:force-refresh"
        );
      });

这效果很好,尽管与路由转换不能完全同步,但没关系。

再次感谢!

3 个赞

顺便说一句,在这里顺便提一下,虽然小部件 API 非常特别且有些棘手(尤其是 hyperscript 部分),但我必须承认,在不覆盖大量代码的情况下,将新行为附加到现有小部件上非常强大。

例如,我经常使用这种模式:

api.reopenWidget('discourse-awesome-widget', {

  html(attrs, state) {
    let contents = this._super(...arguments);

    contents.unshift(h("div.my-cool-new-thing", "很酷的新东西"))

    return contents;
  }
});

this._super 可能涉及大量代码!!!

而且它还可以变得更聪明,让我越来越欣赏它。

我希望它所取代的东西的“可覆盖性”能够同样灵活和强大。

1 个赞

主要解决方案将是插件插槽。一如既往,如果您觉得需要一个不存在的插件,请随时为核心提交一个 PR :rocket:

1 个赞

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.