如何使用插件自定义页眉?

我正在尝试开发一个插件,将头部区域修改为类似这样的样式:


外观具体如何并不重要,重要的是我不想通过 /admin/customize/css_html 路径进行自定义。我希望开发一个插件,能够神奇地修改所有我需要的内容。

目前我发现的是,头部没有对应的模板,它是通过虚拟 DOM(virtual-dom)渲染的。

其渲染流程如下:

  1. assets/javascripts/discourse/templates/application.hbs 模板(可以被重载)渲染 site-header 组件。

    {{plugin-outlet “above-site-header”}}
    {{site-header canSignUp=canSignUp
    showCreateAccount=“showCreateAccount”
    showLogin=“showLogin”
    showKeyboard=“showKeyboardShortcutsHelp”
    toggleMobileView=“toggleMobileView”
    toggleAnonymous=“toggleAnonymous”
    logout=“logout”}}
    {{plugin-outlet “below-site-header”}}

  2. assets/javascripts/discourse/components/site-header.js.es6 组件继承并返回 header 部件(widget)。

    const SiteHeaderComponent = MountWidget.extend(Docking, {
    widget: ‘header’,
    ..
    });

    export default SiteHeaderComponent;

  3. assets/javascripts/discourse/widgets/header.js.es6 部件为头部生成虚拟 DOM。

    export default createWidget(‘header’, {
    tagName: ‘header.d-header.clearfix’,

    html(attrs, state) {}
    });

我的想法

我可以创建一个名为 my-header 的新部件,继承现有的 header,在其中仅更新 html 方法。我不想复制粘贴任何内容,只想重写 html() 方法。

/plugins/discourse-foo/assets/javascripts/discourse/widgets/my-header.js.es6

然后,我可以创建一个名为 my-site-header 的新组件,继承现有的 site-header,仅将其重写以指向 my-header 部件。

/plugins/discourse-foo/assets/javascripts/discourse/components/my-site-header.js.es6

最后,我重载 application 模板,使其显示 my-site-header 组件而不是 site-header

/plugins/discourse-foo/assets/javascripts/discourse/templates/application.hbs

{{plugin-outlet "above-site-header"}}
{{my-site-header canSignUp=canSignUp
              showCreateAccount="showCreateAccount"
              showLogin="showLogin"
              showKeyboard="showKeyboardShortcutsHelp"
              toggleMobileView="toggleMobileView"
              toggleAnonymous="toggleAnonymous"
              logout="logout"}}
{{plugin-outlet "below-site-header"}}

问题是,我该如何扩展所有这些组件和部件?能否请您指点一下正确的做法?谢谢。

Based on the screenshot, this seems like something that is plausible to do with just CSS customizations. That would also be much simpler than writing a plugin and would not require updating with new versions of Discourse code.

Well, I knew you going to say that, that’s why I mentioned that I need a plugin :slight_smile:

First of all, because I want to learn how to do plugins, I’ll have to do whole lot more complicated things later. That menu is just an example.

Secondly, I really need that menu to be a plugin, because:

  1. We may reuse it on different projects;
  2. We need a version control, to roll back sometimes;
  3. Some links will be generated from external json;
  4. I want a clean solution. I believe doing it with a plugin is a clean solution;

Sitepoint use a plugin to override the header.
Take a look here:

Thank you for your link, it will be definitely interesting to see how other people are doing it.

As I see now, they are not extending existing header widget. They just copy-pasted it from the core and customised it.
In that case they have to support that code themselves, and Discourse most likely to break it on next update.