这是创建主题组件的正确方式吗?

我拥有使用其他平台/框架构建自定义解决方案的经验,并希望了解这是否是创建 Discourse 主题组件的正确方法。

它似乎有效,但这并不一定意味着它是正确的方法。

简而言之,这应该会隐藏某个主题所属类别的反应。这是正确的方法吗?

<script type="text/discourse-plugin" version="0.1">
$(document).ready(function() {
    try {
      const isTopicPage = /^\/t\//.test(window.location.pathname);
      
      if (!isTopicPage) return;

      const allowedCategories = ['ask-a-question'];

      const topic = Discourse.__container__.lookup("controller:topic");
      const categorySlug = topic && topic.get("model.category.slug");
      const isAllowedCategory = categorySlug && allowedCategories.includes(categorySlug);

      const toggleReactionEmoji = () => {
        const emoji = document.querySelector("[data-reaction='frog']");
        
        if (emoji) {
          emoji.style.display = isAllowedCategory ? '' : 'none';
          console.log(`Emoji with data-reaction='frog' ${isAllowedCategory ? 'shown' : 'hidden'}.`);
        }
      };

      toggleReactionEmoji();

      const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
          mutation.addedNodes.forEach(node => {
            if (node.nodeType === 1) {
              const emoji = node.querySelector("[data-reaction='frog']");
              if (emoji) {
                emoji.style.display = isAllowedCategory ? '' : 'none';
                console.log(`Emoji with data-reaction='frog' found in mutation and ${isAllowedCategory ? 'shown' : 'hidden'}.`);
              }
            }
          });
        });
      });

      observer.observe(document.body, { childList: true, subtree: true });

      api.cleanupStream(() => observer.disconnect());

    } catch (error) {
      console.error("An error occurred in the emoji toggle script:", error);
    }
  });
</script>

虽然这种方式在技术上可行,但它并不是理想的做法。

与其使用 script 标签和 jQuery 的 $(document).ready,不如更好地利用 Ember 的渲染系统。

首先,建议为你的主题组件创建一个具有合适文件夹结构的主题组件仓库。你可以参考 discourse_theme CLI,它会为你生成这种结构,并让你更容易地开发组件。(另外,如果你只需要结构而不需要主题 CLI 的其他功能,也可以使用 主题骨架)。

接下来,我会使用 Discourse 提供的扩展性工具,例如 apiInitializerspluginAPI、插件出口(plugin outlets)等来实现你想要达到的效果。

了解这些内容的最佳方式是查阅 Meta 上的开发者指南(特别是主题/主题组件部分)。此外,我建议浏览 Customization > Theme component 分类,找到相关的 GitHub 仓库。查看他们的代码以及他们如何实现某些功能也会对你有所帮助。

希望这对你有帮助!

如果这是您的目标,您可以使用简单的 CSS 来实现:

body.category-ask-a-question .discourse-reactions-picker.frog {
  display: none;
}