正确。有两种方法可以解决这个问题……
-
您可以将自定义内容制作成 widget,然后像这样在 plugin outlet 中挂载 widget:
{{mount-widget widget="widget-name"}}您可以在 Discourse 中看到 widget 的创建示例,例如主页 logo:discourse/app/assets/javascripts/discourse/app/widgets/home-logo.js at 2dbcea9eeeb816dda347027497b3a49634ef851f · discourse/discourse · GitHub
在主题中,您会将
widget-name.js文件添加到javascripts/discourse/widgets目录中。关于 widget 的更多信息,请参阅 https://meta.discourse.org/t/a-tour-of-how-the-widget-virtual-dom-code-in-discourse-works/40347,但请注意,我们将逐步淘汰 widget,因此在此过程中学到的任何东西都将无法长期使用。
-
保持 widget 装饰器不变,并创建一个单独的 Ember 组件,在 plugin outlet 中执行您想要的操作。我们一直在用 Ember 组件(Discourse 的大部分内容都是基于此构建的)来取代 widget。
这个过程将是这样的:
-
在主题的
javascripts/discourse/components目录中创建组件的 JS 和 HBS(模板)文件。-
component-name.js -
component-name.hbs
-
-
构建您的 Ember 组件……不幸的是,这一步本质上是“学习 Ember”(Ember Guides)……但我认为这可能会给您一个大致的起点:
- 在
component-name.js中:
import Component from "@glimmer/component"; import { tracked } from "@glimmer/tracking"; import { action } from "@ember/object'; const endpoint = settings.site_navigation_links_endpoint; export default class ComponentName extends Component { @tracked navLinks = null; @action async fetchNavLinks() { try { const response = await fetch(endpoint); const data = await response.json(); // 假设这是 json this.navLinks = data; } catch (error) { console.error("Failed:", error); } } }- 在
component-name.hbs中:
<div {{did-insert this.fetchNavLinks}}> {{#each this.navLinks as |link|}} <a href={{link.anchor}}>{{link.title}}</a> {{/each}} </div>这将调用
fetchNavLinks操作,只要组件被插入(在这种情况下,当您访问 Discourse 站点并渲染应用程序时)。每当navLinks更新时,组件的内容就会更新,因为它是一个被跟踪的属性。如果您想比组件渲染时更频繁地更新链接,您需要在此处添加更多逻辑到 JS 中……例如检查当前路由(页面)是否满足特定条件。
- 在
-
通过在
javascripts/discourse/connectors/below-site-header/my-component-connector.hbs中将其添加到 outlet 来将此组件添加到 plugin outlet:<ComponentName />
-