-
Ich verwende nur Widgets über UiBinder, wenn das Widget extrem einfach ist. Zum Beispiel füge ich gerade zwei Widgets zu einem Panel
hinzu. Wenn CSS involviert ist, gehe ich immer mit UiBinder, weil es viel einfacher ist, mit Styles zu arbeiten.
-
Widgets werden nicht in UiBinder XML übersetzt. Der gesamte GWT-Code wird zu JavaScript, das DOM-Elemente hinzufügt und manipuliert, daher wird alles in eine ausführbare Sprache übersetzt, nicht in ein Templatesystem.
-
Ich schreibe viele UiBinder-Schnipsel. Ich versuche, gute Regeln über Abstraktion und Komposition zu befolgen, die Sie überall im Web finden können.
-
Das MVP-Muster ist ein Muss, wenn Sie irgendeine nicht triviale Logik haben, weil das Testen eines GWT-freien Presenters mit JUnit sehr schnell und einfach ist, während GWT-Tests viel mehr Overhead haben und viel langsamer sind.
-
Ich halte so viel Styling wie möglich in CSS-Dateien, weil es eine Standardpraxis ist, Bedenken zu trennen, Sie können Ihre CSS-Dateien komprimieren und bündeln und viele andere Gründe, die dieselben sind wie bei einer normalen HTML-Seite, auf der CSS in separaten Dateien und nicht direkt auf der Seite platziert wird.
-
Ich verwende nie den GWT-Designer. Ich ziehe es immer vor, sauberen Code zu haben, anstatt den verrückten Müll zu erhalten, der in der Regel von jedem UI-Code-Generator ausgegeben wird.
-
99% der Zeit erweitern meine Widgets Composite
, weil ich entweder UiBinder verwende oder Dinge zu einem Panel
hinzufüge. Selbst wenn ich nur ein einzelnes Widget habe, finde ich es einfacher, Composite
zu erweitern und mein Widget zu einem SimplePanel
hinzuzufügen. Ich erweitere selten Widget
, weil Sie dann einen Aufruf an Document.get().createFooElement()
machen müssen, um ein DOM-Element
zu erstellen, aber ich finde Widget
s, die zu Panel
s hinzugefügt werden können, einfacher und sicherer zu verarbeiten als Element
s
Wie ich Widgets erstelle
Jedes Widget implementiert eine Schnittstelle, die IsWidget
erweitert. Alle, die das Widget verwenden möchten, sollten von der Schnittstelle abhängen, nicht von der zugrunde liegenden Klasse. Dies stellt eine einzige, JSNI-freie Abstraktion dar.
Wenn das Widget sehr einfach ist, habe ich eine einzelne Klasse, die Composite
erweitert und die Schnittstelle implementiert. Entweder das Widget ist sehr einfach und fügt ein paar Elemente zu einem Panel
hinzu oder es verwendet UiBinder.
Wenn das Widget eine nicht triviale Logik hat, die ich testen möchte, verwende ich das MVP-Muster. Es wird eine Presenter-Klasse geben, die das 'public'-Interface des Widgets implementiert, eine View-Schnittstelle, die IsWidget
erweitert, von der der Presenter abhängt, und ein View-Widget, das die View-Schnittstelle implementiert.
Ein Vorteil der Verwendung einer einzigen 'public'-Schnittstelle für das Widget ist, dass Sie von der Implementierung der Schnittstelle mit einer einzigen Composite
-Klasse auf MVP umsteigen können, wenn die Logik komplex wird, und niemand, der das Widget verwendet, muss sich überhaupt ändern.
Ich verwende Gin, um alle Schnittstellen und Implementierungen miteinander zu verbinden.
Beispiel
Das wird am besten mit etwas Code erklärt. Angenommen, ich habe ein Diagramm, das auf mehreren Seiten verwendet werden soll, also entscheide ich mich, ein wiederverwendbares Widget dafür zu erstellen. Es gibt einige nicht triviale Logik für die Verarbeitung der RPC-Antwort, bevor sie angezeigt wird, also möchte ich sie gründlich unit testen. Ich würde etwas in dieser Art verwenden:
public interface FinancialChart extends IsWidget {
void setTickerSymbol(String tickerSymbol);
}
class FinancialChartPresenter extends Composite implements FinancialChart {
private final FinancialChartView view;
private final DataServiceAsync service;
@Inject(FinancialChartView view, DataServiceAsync service) {
this.view = view;
this.service = service;
}
@Override public Widget asWidget() {
return view.asWidget();
}
@Override public void setTickerSymbol(String tickerSymbol) {
service.getData(tickerSymbol, new AsyncCallback() {
@Override public void onFailure(Throwable t) {
// Fehler behandeln
}
@Override public void onSuccess(FinancialData data) {
SimpleData simpleData = // Führen Sie etwas Parsing mit präsentationsspezifischer
// Logik durch, z.B. machen Sie dramatische Preiserhöhungen oder -senkungen in einer
// anderen Farbe, damit sie hervorstechen. Enden Sie mit etwas Einfachem,
// das im Wesentlichen einige (x, y)-Punkte sind, die das dumme Views plotten können,
// zusammen mit einem Label und einer Farbe für jeden Punkt.
view.drawGraph(simpleData);
}
}
}
interface FinancialChartView extends IsWidget {
void drawGraph(SimpleData simpleData);
}
class FinancialChartWidget extends Composite implements FinancialChartView {
@Override public void drawGraph(SimpleData simpleData) {
// Punkte in einem Diagramm plotten. Beschriften usw.
}
}
class SomethingWithFinancialChartWidget extends Composite
implements SomethingWithFinancialChart {
interface Binder extends UiBinder {}
@UiField(provided = true) final FinancialChart chart;
@Inject SomethingWithFinancialChartWidget(Binder binder, FinancialChart chart) {
this.chart = chart;
initWidget(binder.createAndBindUi(this));
}
}
// In SomethingWithFinancialChartWidget.ui.xml
class MyPackagesGinModule extends AbstractGinModule {
@Override protected void configure() {
bind(FinancialChart.class).to(FinancialChartPresenter.class);
bind(FinancialChartView.class).to(FinancialChartWidget.class);
}
}
Das ermöglicht es mir, sehr einfache, gründliche und schnelle JUnit-Tests für den FinancialViewPresenter
zu schreiben, weil er keine GWT-Abhängigkeiten hat, die JSNI erfordern, der in einem Browser als Teil eines wesentlich langsameren GWT-Testfalls ausgeführt werden muss. Sie können ein Mock-FinancialChartView
erstellen.
Eine Sache, die hier zu beachten ist, ist, dass da SomethingWithFinancialChartWidget
von der Schnittstelle FinancialChart
abhängt, kann es dieses Objekt nicht instanziieren, weil es nur eine Schnittstelle ist. Deshalb wird chart
im Java-Code von SomethingWithFinancialChartWidget
als @UiField(provided = true)
eingerichtet. Gin richten die Bindung von der Schnittstelle FinancialChart
zu einer konkreten Klasse ein, damit es eine Implementierung für den @Inject
-Konstruktor von SomethingWithFinancialChartWidget
bereitstellen kann, und dann das Setzen von this.chart
Es werden viele Dateien für alle Schnittstellen und Implementierungen in MVP erstellt, aber die Abstraktion ist absolut lohnenswert, weil sie einfache Unit-Tests für Presenter ermöglichen und es Ihnen ermöglichen, zu ändern, wie die Top-Level-Schnittstelle, FinancialChart
in diesem Beispiel, implementiert wird, z.B. Wechsel von einer einzelnen Composite
-Klasse zu MVP, ohne dass der Client etwas ändern muss.
Sicher gibt es einige Implementierungsdetails, die möglicherweise nicht super klar sind oder Dinge, die ich übersehen habe, z.B. GWT-Tests, also bitte posten Sie Kommentare und ich kann meine Antwort aktualisieren und präzisieren.
2 Stimmen
Tolle Frage, dieser Art von Dingen ist für einen Neuling ziemlich schwer zu verstehen. Würde gerne eine ausführliche Antwort von einem erfahrenen GWT UI Veteran sehen.
0 Stimmen
Als jemand, der in der Vergangenheit mit GWT gearbeitet hat und in seiner Freizeit etwas JS-fu betreibt, rate ich dringend davon ab, GWT zu verwenden, wenn es nicht unbedingt notwendig ist. Auch wenn es Ihnen helfen kann, große Webanwendungen zu verwalten, ist es für kleine bis mittelgroße Webanwendungen viel zu schwerwiegend. Das Erlernen von JS ist ziemlich einfach (auch mit seinen Eigenheiten) und kann sich langfristig auszahlen. Dies mag wie eine Tirade klingen, aber das waren meine Erfahrungen mit GWT. Es soll nicht heißen, dass es nutzlos ist, aber für die meisten Webanwendungen ist es überdimensioniert.