Ember-Komponenten zu Discourse hinzufügen

Im vorherigen Tutorial habe ich gezeigt, wie man sowohl die Server- als auch die Client-Seite von Discourse so konfiguriert, dass sie auf eine Anfrage reagieren.

Wir empfehlen dir nun, die Dokumentation zu Ember-Komponenten zu lesen: Introducing Components - Components - Ember Guides

Bevor du eine Komponente schreibst, prüfe das UI-Kit mit geteilten Komponenten, Helpers und Modifiern; die meisten gängigen Steuerelemente existieren dort bereits.

Altes Tutorial

In diesem Tutorial werde ich eine neue Ember-Komponente erstellen, um Drittanbieter-JavaScript einzukapseln. Dies wird ähnlich wie einem YouTube-Video sein, das ich vor einiger Zeit erstellt habe und das du vielleicht informativ findest, nur dass es diesmal spezifisch für Discourse und die Art und Weise ist, wie wir Dateien in unserem Projekt anordnen.

Warum Komponenten?

Handlebars ist eine recht einfache und verlockende Sprache. Es ist nichts weiter als normales HTML mit einigen dynamischen Teilen. Das ist einfach zu lernen und großartig für die Produktivität, aber nicht so gut für die Wiederverwendbarkeit von Code. Wenn du eine große Anwendung wie Discourse entwickelst, wirst du feststellen, dass du dieselben Dinge immer wieder wiederverwenden möchtest.

Komponenten sind Embers Lösung für dieses Problem. Erstellen wir eine Komponente, die unseren Snack auf eine schönere Weise anzeigt.

Eine neue Komponente erstellen

Komponenten müssen einen Bindestrich in ihrem Namen haben. Ich werde fancy-snack als Namen für diese Komponente wählen. Erstellen wir unsere Vorlage:

app/assets/javascripts/admin/templates/components/fancy-snack.hbs

<div class="fancy-snack-title">
  <h1>{{snack.name}}</h1>
</div>

<div class="fancy-snack-description">
  <p>{{snack.description}}</p>
</div>

Nun werden wir, um unsere Komponente zu verwenden, unsere bestehende admin/snack-Vorlage ersetzen mit:

app/assets/javascripts/admin/templates/snack.hbs

{{fancy-snack snack=model}}

Wir können unsere fancy-snack-Komponente nun in jeder anderen Vorlage wiederverwenden, indem wir einfach das benötigte Modell übergeben.

Hinzufügen von benutzerdefiniertem JavaScript-Code

Neben der Wiederverwendbarkeit sind Komponenten in Ember großartig, um benutzerdefiniertes JavaScript, jQuery und anderen externen Code sicher hinzuzufügen. Sie geben dir die Kontrolle darüber, wann die Komponente in die Seite eingefügt wird und wann sie entfernt wird. Um dies zu tun, definieren wir eine Ember.Component mit etwas Code:

app/assets/javascripts/admin/components/fancy-snack.js

export default Ember.Component.extend({
  didInsertElement() {
    this._super();
    this.$().animate({ backgroundColor: "yellow" }, 2000);
  },

  willDestroyElement() {
    this._super();
    this.$().stop();
  },
});

Wenn du den obenstehenden Code hinzufügst und die Seite aktualisierst, wirst du sehen, dass unser Snack eine Animation mit langsam verblassendem gelbem Hintergrund hat.

Erklären wir, was hier passiert:

  1. Wenn die Komponente auf der Seite gerendert wird, ruft sie didInsertElement auf.

  2. Die erste Zeile von didInsertElement (und willDestroyElement) ist this._super(), was notwendig ist, weil wir eine Unterklasse von Ember.Component erstellen.

  3. Die Animation wird mit der jQuery-Funktion animate durchgeführt.

  4. Schließlich wird die Animation im willDestroyElement-Hook abgebrochen, der aufgerufen wird, wenn die Komponente von der Seite entfernt wird.

Du magst dich fragen, warum uns willDestroyElement überhaupt wichtig ist; der Grund ist, dass es in einer langlebigen JavaScript-Anwendung wie Discourse wichtig ist, nach uns aufzuräumen, damit wir keinen Speicher auslaufen lassen oder Dinge laufen lassen. In diesem Fall stoppen wir die Animation, was allen jQuery-Timern mitteilt, dass sie nicht mehr feuern müssen, da die Komponente nicht mehr auf der Seite sichtbar ist.

Wo geht es von hier aus weiter

Das letzte Tutorial in dieser Serie behandelt das automatisierte Testen.


Dieses Dokument wird versioniert – schlage Änderungen auf GitHub vor.

18 „Gefällt mir“

Hi, how do i extend a discourse component thru a plugin? Can you give me some points. Thanks

1 „Gefällt mir“

Generally we prefer you don’t extend Discourse plugins, and you stick to plugin outlets or using the widget decoration API to add stuff.

But if you must, you can create an initializer and use Ember’s extend code. Here’s an example that extends an Ember object.

4 „Gefällt mir“

Tried with initializer but didnt worked. What i actually want to do is to add 2 more classNames and some actions:

import { withPluginApi } from 'discourse/lib/plugin-api';

function initializeComponentTopicList(api) {
  // extend component from jsapp/components/topic-list.js.es6
  const TopicList = api.container.lookupFactory('component:topic-list');

  TopicList.extend({
    classNames: ['topic-list', 'round', 'table'],
    actions: {
        clickMe: function() {
            console.log('click');
        }
    }
  });
};

export default {
  name: "extend-for-component-topic-list",

  initialize() {
    withPluginApi('0.1', initializeComponentTopicList);
  }
};

And by “didnt worked”, i mean that topic list completly disappeared from page.
Thank you

Were there any logs in the console?

Nope, no logs at all. However i managed to fix it this way. I hope it will help someone.

import { default as TopicList } from 'discourse/components/topic-list';
import { withPluginApi } from 'discourse/lib/plugin-api';

function initializeComponentTopicList(api) {
  TopicList.reopen({
    classNames: ['topic-list', 'round', 'table'],
  });
};

export default {
  name: "extend-for-component-topic-list",

  initialize() {
    withPluginApi('0.1', initializeComponentTopicList);
  }
};
3 „Gefällt mir“

I just ran into the same problem. Add the following as a css/html customisation and observe empty user cards:

<script type="text/discourse-plugin" version="0.5">
    api.container.lookupFactory('component:user-card-contents')
</script>
2 „Gefällt mir“

Es wäre schön, hier eine aktualisierte Dokumentation zu sehen, die auf die Dokumentation der Glimmer-Komponenten verweisen könnte.

3 „Gefällt mir“