Reihenfolge der Priorität von Theme-Komponenten

Ich habe bemerkt, dass Theme-Komponenten in der Reihenfolge ihrer Installation ausgeführt werden. Wenn ich also zuerst A und dann B installiere, werden die Skripte von A vor denen von B in den generierten Seiten eingebunden.

Kann ich mich darauf verlassen? Gibt es eine Ansicht, die diese Reihenfolge anzeigt? Bei der Anzeige der installierten Komponenten werden diese alphabetisch aufgelistet.

Ich bevorzuge eine Möglichkeit, Aktionen explizit vor einer bestimmten Komponente auszuführen. In meinem Fall möchte ich Aktionen vor der TOC-Komponente ausführen (bezogen auf dieses Thema). Laut der Ember-Dokumentation werden geplante Funktionen für eine bestimmte Warteschlange in der Reihenfolge ihrer Planung ausgeführt. In meinem Fall ist die Reihenfolge der Planung daher entscheidend.

2 „Gefällt mir“

Darauf kannst du dich nicht verlassen; stattdessen sollten ordnungsgemäße APIs dies steuern. Du kannst Ember-Initializer verwenden, um dies bis zu einem gewissen Grad zu kontrollieren. @eviltrout hat möglicherweise einige konkrete Ideen, wenn du den Beispielcode, den du zu planen versuchst, hier einfügst.

7 „Gefällt mir“

Dies ist der Code, den ich ausführe:

<script type="text/discourse-plugin" version="0.8">
    const { run } = Ember;
    
    api.decorateCooked($elem => {
        run.scheduleOnce("actions", () => {
          // Muss vor den geplanten Aktionen der TOC-Komponente ausgeführt werden.
        });
    })

Die TOC-Komponente verwendet dieselbe Schnittstelle, um ihre Aktionen zu planen.

Laut der Ember-Dokumentation ist die Schnittstelle zum Planen:

Fügt das übergebene Ziel/die übergebene Methode sowie alle optionalen Argumente zur benannten Warteschlange hinzu, die am Ende des RunLoop ausgeführt werden soll.

Der Begriff „hinzufügen“ deutet auf eine FIFO-Reihenfolge der geplanten Aktionen hin. Daher ist die Reihenfolge des Aufrufs von schedule hier entscheidend.

Mir ist aufgefallen, dass sich beim Versuch, die JavaScript-Ausführung neu zu ordnen, indem ich die TOC-Komponente neu installiert und dann wieder deinstalliert habe (was scheinbar den glücklichen Nebeneffekt hat, dass das TOC-JavaScript zuletzt ausgeführt wird), die CSS-Regeln nun in dieser Reihenfolge angewendet werden :slight_smile:

Ich finde, das Thema der Reihenfolge bei der Platzierung von Theme-Komponenten-Code ist ziemlich wichtig. Wenn die Reihenfolge offiziell als „nicht definiert“ gilt, können Komponenten nicht darauf hoffen, miteinander zu interagieren.

Vielleicht ist die Interaktion zwischen Komponenten gar kein Ziel. Aber ich denke, mit einer Heuristik zur Reihenfolge (z. B. festzulegen, dass eine Komponentendatei vor oder nach einer anderen Komponentendatei mit demselben Namen erscheint – dies müsste vermutlich in about.json definiert sein), ist dieses Problem nicht allzu schwer zu lösen.

Für meinen Teil beginne ich zu glauben, dass das Forken der TOC-Komponente angesichts dessen, was ich erreichen möchte, der richtige Weg ist.

Jedes Mal, wenn Sie ein Theme oder eine Komponente erstellen oder installieren, weist Discourse dieser eine ID zu. Wenn Sie die Seite dieser Komponente besuchen, sollten Sie diese ID in der URL sehen (die Zahl am Ende).

component id in the URL

Wenn diese Komponente zu Ihrem Theme hinzugefügt wird, scheint ihre Ausführungsreihenfolge – auf sehr einfacher Ebene (ohne Verzögerung, z. B. durch ein einfaches console.log) – von ihrer ID abhängig zu sein. Das bedeutet: 233 wird vor 234 ausgeführt und so weiter.

Das funktioniert in den meisten Fällen, da nachfolgende Änderungen üblicherweise in neuen Komponenten vorgenommen werden, sodass alles einfach funktioniert.

Langfristig könnte die Reihenfolge der Liste der Komponenten entsprechen, die Sie zu Ihrem Theme hinzugefügt haben.

Dies steht jedoch derzeit nicht auf der Roadmap.

Was Sie wirklich benötigen, ist die Reihenfolge der Initialisierer. Ich glaube nicht, dass dies möglich ist, es sei denn, Sie verlagern Ihren Code in die neue Methode zur Erstellung von Theme-JS. Diese Methode ermöglicht es Ihnen, einem Initialisierer einen Namen und eine Ausführungsreihenfolge zuzuweisen. Nehmen wir beispielsweise an, ich habe folgende Datei:

/javascripts/discourse/initializers/initialize-for-foo.js

und sie sieht so aus:

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

export default {
  name: "foo",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("foo")
    });
  }
}

Und ich habe einen weiteren Initialisierer, der so aussieht:

/javascripts/discourse/initializers/initialize-for-bar.js

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

export default {
  name: "bar",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("bar")
    });
  }
}

Wenn ich sicherstellen möchte, dass bar nach foo ausgeführt wird, kann ich ein after:-Argument hinzufügen. Dadurch wird gewährleistet, dass der Initialisierer nach dem angegebenen Namen ausgeführt wird. Um also bar nach foo auszuführen, würde ich in

/javascripts/discourse/initializers/initialize-for-bar.js

folgendes tun:

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

export default {
  name: "bar",
+ after: "foo",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("bar");
    });
  }
};
6 „Gefällt mir“

Vielen Dank für die detaillierten Hinweise! Angesichts meiner damit zusammenhängenden Probleme mit der TOC-Komponente (auf die Sie ebenfalls geantwortet haben – vielen Dank nochmals) habe ich TOC geforkt und den abhängigen Code in diese Komponente verschoben. Dies hängt mit den Überschriften-IDs zusammen – insbesondere mit der Notwendigkeit, sie von der Seite aus zu steuern, um Duplikate und Kollisionen mit IDs von Kernelementen zu vermeiden.

Ich denke, angesichts dessen, was ich mit der Dokumentation mache – teilweise etwas abseits des Mainstreams –, ist das der richtige Ansatz.

1 „Gefällt mir“