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

**URL:** https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697
**Category:** Development
**Created:** [2023 年4 月 24 日 11:57 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697 "2023-04-24T11:57:57Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2023 年4 月 24 日 11:57 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/1 "2023-04-24T11:57:57Z")

</div>

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

```plaintext
      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](https://github.com/discourse/discourse/blob/4aa81e709ea49e30383a3a3acd33dfedaebfc240/app/assets/javascripts/discourse/app/widgets/header-contents.js#L1) 中的原始模板 _完全相同_

它正在生成一个错误：

 ![image](https://global.discourse-cdn.com/meta/original/4X/c/6/9/c6961cd15c1365c93b9cc3093c8faf7241488213.png)

这出乎意料，尤其是我实际上并没有“更改任何内容”（目前）？

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

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

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

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

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

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2023 年4 月 24 日 12:22 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/2 "2023-04-24T12:22:11Z")

</div>

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

> [@merefield](#):
>
> 这出乎意料，尤其是因为我实际上并没有“更改任何内容”（目前）？

您能否分享更多您的文件（例如，`hbs` 是从哪里导入的？）

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2023 年4 月 24 日 12:26 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/3 "2023-04-24T12:26:11Z")

</div>

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

> <https://github.com/discourse/discourse/blob/3e414996c2/app/assets/javascripts/discourse/app/components/site-header.js#L337-L337>

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2023 年4 月 24 日 12:47 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/4 "2023-04-24T12:47:04Z")

</div>

好的。

> [@david](#):
>
> 可以分享更多你的文件吗（例如，`hbs` 是从哪里导入的？）

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

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

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

```plaintext
      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");
        }
      });

```

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

> [@david](#):
>
> 另外，这是哪个版本的 Discourse？`site-header.js:337` 目前没有引用“header”变量

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

我看到了这个提交，我需要更新我的开发实例…… [PERF: Memoize element references for `dockCheck` (#21079) · discourse/discourse@db16700 · GitHub](https://github.com/discourse/discourse/commit/db16700355db6f76b6d88bdc47a18259a9ee77ff)

无论如何我都会回滚，感谢你的时间！

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2023 年4 月 24 日 12:50 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/5 "2023-04-24T12:50:21Z")

</div>

> [@merefield](#):
>
> `import { hbs } from "ember-cli-htmlbars";`

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

> <https://github.com/discourse/discourse/blob/3e414996c24efac125e0f26fb6af1e4ae5f46748/app/assets/javascripts/discourse/app/widgets/header-contents.js#L2-L2>

> [@merefield](#):
>
> 在某些路由转换之间重新评估，

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

> <https://github.com/discourse/discourse/blob/3e414996c24efac125e0f26fb6af1e4ae5f46748/app/assets/javascripts/discourse/app/components/site-header.js#L457-L457>

（示例触发器在此处 [here](https://github.com/discourse/discourse/blob/3e414996c24efac125e0f26fb6af1e4ae5f46748/app/assets/javascripts/discourse/app/initializers/narrow-desktop.js#L33-L35)）

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2023 年4 月 24 日 12:51 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/6 "2023-04-24T12:51:22Z")

</div>

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

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2023 年4 月 25 日 11:49 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/7 "2023-04-25T11:49:03Z")

</div>

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

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

```

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

再次感谢！

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [2023 年5 月 9 日 20:23 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/8 "2023-05-09T20:23:07Z")

</div>

> [@david](#):
>
> 我们真的不想在这里投入太多时间——小部件不会存在太久了。

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

例如，我经常使用这种模式：

```plaintext
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` 可能涉及大量代码！！！

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

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

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2023 年5 月 10 日 08:03 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/9 "2023-05-10T08:03:01Z")

</div>

> [@merefield](#):
>
> 我希望任何替代它的“可覆盖性”都能同样灵活和强大。

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

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [2023 年6 月 9 日 08:03 UTC](https://meta.discourse.org/t/re-evaluate-widgets-in-header-upon-route-change-without-error/262697/10 "2023-06-09T08:03:22Z")

</div>

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