仅在特定页面覆盖模板

你好,我一直在主题的自定义 </head> 字段中自定义我的 Discourse 外观。
我使用 script type="text/x-handlebars" data-template-name="components/categories-only" 以及类似的方式来覆盖某些特定模板。有没有办法仅在特定页面(如首页)上覆盖它,并在子分类视图中使用不同的代码?我刚开始接触 Discourse,甚至不确定在主题的自定义 HTML/CSS 中这样做是否正确(我知道更新时会丢失这些更改)。如果有人能帮我解决这个问题,我将不胜感激。


首先澄清一下这一点:

这是不正确的。如果修改是在主题中进行的,更新时不会丢失这些更改,它们会保留下来。唯一会丢失更改的情况是直接在服务器上编辑文件,而这显然是不应该做的。

不过,覆盖模板确实存在一定的风险,因为核心更新可能导致您的更改不再兼容,需要随之更新。如果您能接受这种风险,那么从技术上讲,您完全可以实现此处所请求的功能。

首先,您需要一种方法来区分用户是否在首页。对于仅分类组件,一种方法是检查 searchContext。当您在子分类页面时,search context 会被设置为 “category”。如果没有 search context,则说明您正在首页。

要将此信息传递给模板,您可以添加如下代码:

<script type="text/discourse-plugin"
        version="0.8">
  const categoriesOnlyComponent = require('discourse/components/categories-only').default;
  categoriesOnlyComponent.reopen({
    isHomepage: function() {
      return !this.parentView.searchService.contextType
    }.property()
  });
</script>

这段代码的作用是让您可以在 categories-only 模板中使用 isHomepage。如果没有 search context(即用户在首页),它返回 true;否则返回 false

接下来,您需要复制默认模板,如下所示:

<script type='text/x-handlebars'
        data-template-name='components/categories-only'>
  {{#if categories}}
  ... 模板其余部分
  {{/if}}
</script>

然后使用我们添加的 isHomepage。为此,您需要使用 Handlebars 的 {{#if}} 辅助函数。本质上,您需要类似以下的代码:

<script type='text/x-handlebars'
        data-template-name='components/categories-only'>
  {{#if categories}}
    {{#if isHomepage}}
      ... 仅适用于首页的模板
    {{else}}
    ... 非首页时的默认模板其余部分
  {{/if}}
</script>

现在,您可以在 isHomepage 部分使用任何您想要的内容。您可以直接在此处编辑,也可以为该部分创建一个新的模板,如下所示:

<script type='text/x-handlebars'
        data-template-name='components/categories-only-homepage'>
  <h1>您正在首页!</h1>
  <p>
    如果用户在首页,请使用此部分来渲染仅分类组件的模板。此部分仅适用于首页。
  </p>
</script>

最后一步是在 categories-only 模板的 isHomepage 部分以内联方式调用该模板,如下所示:

<script type='text/x-handlebars'
        data-template-name='components/categories-only'>
  {{#if categories}}
    {{#if isHomepage}}
      {{partial 'components/categories-only-homepage'}}
    {{else}}
    ... 非首页时的默认模板其余部分
  {{/if}}
</script>

这样,当您访问首页时,您将看到如下内容:

但子分类中的组件将保持不变。

这一步是可选的,但您可能也对以下内容感兴趣:

因为这是目前推荐的处理主题的方式,可以避免使用 <script> 标签。

太棒了,非常感谢!现在我也大致了解如何使用 text/discourse-plugin 了。非常感激!

嘿,我想再问一个问题。
你能告诉我如何获取特定子分类中的最新主题吗?我可以使用 category.latestTopic 来获取分类的最新主题,但无法用于子分类。有什么巧妙的变通方法吗?我希望在列出子分类时,能显示每个子分类的最新主题。