Bevor Sie einen neuen Feldtyp erstellen, sollten Sie prüfen, ob eine der anderen Methoden zum Anpassen von Feldern Ihren Anforderungen entspricht. Wenn in Ihrer Anwendung ein neuer Werttyp gespeichert werden muss oder Sie eine neue Benutzeroberfläche für einen vorhandenen Werttyp erstellen möchten, müssen Sie wahrscheinlich einen neuen Feldtyp erstellen.
So erstellen Sie ein neues Feld:
- Implementieren Sie einen Konstruktor.
- Registrieren Sie einen JSON-Schlüssel und implementieren Sie
fromJson
. - Initialisierung der On-Block-UI und Ereignis-Listener verwalten
- Entsorgung von Ereignis-Listenern verwalten (die Entsorgung der Benutzeroberfläche wird für Sie erledigt).
- Wertbehandlung implementieren
- Fügen Sie aus Gründen der Barrierefreiheit eine Textdarstellung des Feldwerts hinzu.
- Fügen Sie zusätzliche Funktionen hinzu, z. B.:
- Konfigurieren Sie weitere Aspekte des Felds, z. B.:
In diesem Abschnitt wird davon ausgegangen, dass Sie den Artikel Anatomy of a Field (Anatomie eines Felds) gelesen und verstanden haben.
Ein Beispiel für ein benutzerdefiniertes Feld finden Sie in der Demo zu benutzerdefinierten Feldern.
Konstruktor implementieren
Der Konstruktor des Felds ist für die Einrichtung des Anfangswerts des Felds und optional für die Einrichtung eines lokalen Validators verantwortlich. Der Konstruktor des benutzerdefinierten Felds wird während der Initialisierung des Quellblocks aufgerufen, unabhängig davon, ob der Quellblock in JSON oder JavaScript definiert ist. Das benutzerdefinierte Feld hat also während der Erstellung keinen Zugriff auf den Quellblock.
Im folgenden Codebeispiel wird ein benutzerdefiniertes Feld mit dem Namen GenericField
erstellt:
class GenericField extends Blockly.Field {
constructor(value, validator) {
super(value, validator);
this.SERIALIZABLE = true;
}
}
Methodensignatur
Feldkonstruktoren nehmen in der Regel einen Wert und einen lokalen Validator an. Der Wert ist optional. Wenn Sie keinen Wert übergeben (oder einen Wert übergeben, der die Klassenüberprüfung nicht besteht), wird der Standardwert der Superklasse verwendet. Für die Standardklasse Field
ist das null
. Wenn Sie diesen Standardwert nicht verwenden möchten, müssen Sie einen geeigneten Wert übergeben. Der Validatorparameter ist nur für bearbeitbare Felder vorhanden und wird in der Regel als optional gekennzeichnet. Weitere Informationen zu Validatoren finden Sie in den Validator-Dokumenten.
Struktur
Die Logik in Ihrem Konstruktor sollte diesem Ablauf folgen:
- Rufen Sie den übergeordneten Konstruktor auf (alle benutzerdefinierten Felder sollten von
Blockly.Field
oder einer ihrer Unterklassen abgeleitet sein), um den Wert richtig zu initialisieren und den lokalen Validator für Ihr Feld festzulegen. - Wenn Ihr Feld serialisierbar ist, legen Sie die entsprechende Eigenschaft im Konstruktor fest. Bearbeitbare Felder müssen serialisierbar sein. Da Felder standardmäßig bearbeitbar sind, sollten Sie diese Property auf „wahr“ setzen, es sei denn, Sie wissen, dass sie nicht serialisierbar sein soll.
- Optional: Sie können zusätzliche Anpassungen vornehmen. Beispielsweise können Sie über Labelfelder eine CSS-Klasse übergeben, die dann auf den Text angewendet wird.
JSON und Registrierung
In JSON-Blockdefinitionen werden Felder durch einen String beschrieben (z.B. field_number
, field_textinput
). Blockly verwaltet eine Zuordnung dieser Strings zu Feldobjekten und ruft während der Konstruktion fromJson
für das entsprechende Objekt auf.
Rufen Sie Blockly.fieldRegistry.register
auf, um dieser Karte den Feldtyp hinzuzufügen, und übergeben Sie die Feldklasse als zweites Argument:
Blockly.fieldRegistry.register('field_generic', GenericField);
Außerdem müssen Sie Ihre fromJson
-Funktion definieren. In Ihrer Implementierung sollten Sie zuerst alle Verweise auf Lokalisierungstokens mit replaceMessageReferences auflösen und dann die Werte an den Konstruktor übergeben.
GenericField.fromJson = function(options) {
const value = Blockly.utils.parsing.replaceMessageReferences(
options['value']);
return new CustomFields.GenericField(value);
};
Wird initialisiert
Wenn das Feld erstellt wird, enthält es im Grunde nur einen Wert. Bei der Initialisierung wird das DOM erstellt, das Modell erstellt (falls das Feld ein Modell hat) und Ereignisse gebunden.
Blockanzeige
Während der Initialisierung müssen Sie alles erstellen, was Sie für die Blockanzeige des Felds benötigen.
Standardeinstellungen, Hintergrund und Text
Mit der Standardfunktion initView
werden ein helles rect
-Element und ein text
-Element erstellt. Wenn Ihr Feld beides und noch einige zusätzliche Funktionen haben soll, rufen Sie die initView
-Funktion der Superklasse auf, bevor Sie die restlichen DOM-Elemente hinzufügen. Wenn Ihr Feld nur eines dieser Elemente enthalten soll, können Sie die Funktionen createBorderRect_
oder createTextElement_
verwenden.
DOM-Aufbau anpassen
Wenn es sich bei Ihrem Feld um ein generisches Textfeld handelt (z.B. Textinput), wird die DOM-Erstellung für Sie übernommen. Andernfalls müssen Sie die initView
-Funktion überschreiben, um die DOM-Elemente zu erstellen, die Sie beim zukünftigen Rendern des Felds benötigen.
Ein Drop-down-Feld kann beispielsweise sowohl Bilder als auch Text enthalten. In initView
werden ein einzelnes Bildelement und ein einzelnes Textelement erstellt. Während render_
wird dann je nach Typ der ausgewählten Option das aktive Element angezeigt und das andere ausgeblendet.
DOM-Elemente können entweder mit der Methode Blockly.utils.dom.createSvgElement
oder mit herkömmlichen Methoden zum Erstellen von DOM-Elementen erstellt werden.
Für die Blockanzeige eines Felds gelten folgende Anforderungen:
- Alle DOM-Elemente müssen untergeordnete Elemente des
fieldGroup_
-Elements des Felds sein. Die Feldgruppe wird automatisch erstellt. - Alle DOM-Elemente müssen sich innerhalb der angegebenen Abmessungen des Felds befinden.
Weitere Informationen zum Anpassen und Aktualisieren von Anzeigen im Block finden Sie im Abschnitt Rendering.
Textsymbole hinzufügen
Wenn Sie dem Text eines Felds Symbole hinzufügen möchten, z. B. das Gradsymbol für das Feld Winkel, können Sie das Symbolelement (normalerweise in einer <tspan>
enthalten) direkt an das textElement_
des Felds anhängen.
Eingabe-Ereignisse
Standardmäßig werden für Felder Tooltip-Ereignisse und mousedown-Ereignisse registriert, die zum Anzeigen von Editoren verwendet werden.
Wenn Sie auf andere Arten von Ereignissen reagieren möchten (z.B. wenn Sie das Ziehen eines Feldes verarbeiten möchten), sollten Sie die bindEvents_
-Funktion des Felds überschreiben.
bindEvents_() {
// Call the superclass function to preserve the default behavior as well.
super.bindEvents_();
// Then register your own additional event listeners.
this.mouseDownWrapper_ =
Blockly.browserEvents.conditionalBind(this.getClickTarget_(), 'mousedown', this,
function(event) {
this.originalMouseX_ = event.clientX;
this.isMouseDown_ = true;
this.originalValue_ = this.getValue();
event.stopPropagation();
}
);
this.mouseMoveWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mousemove', this,
function(event) {
if (!this.isMouseDown_) {
return;
}
var delta = event.clientX - this.originalMouseX_;
this.setValue(this.originalValue_ + delta);
}
);
this.mouseUpWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mouseup', this,
function(_event) {
this.isMouseDown_ = false;
}
);
}
Zum Binden an ein Ereignis sollten Sie im Allgemeinen die Funktion Blockly.utils.browserEvents.conditionalBind
verwenden. Bei dieser Methode der Ereignisbindung werden sekundäre Berührungen während des Ziehens herausgefiltert. Wenn Ihr Handler auch während eines laufenden Ziehens ausgeführt werden soll, können Sie die Funktion Blockly.browserEvents.bind
verwenden.
Entsorgung
Wenn Sie benutzerdefinierte Ereignisempfänger in der bindEvents_
-Funktion des Felds registriert haben, müssen Sie sie in der dispose
-Funktion abmelden.
Wenn Sie die Ansicht des Felds korrekt initialisiert haben, indem Sie alle DOM-Elemente an fieldGroup_
angehängt haben, wird das DOM des Felds automatisch entfernt.
Umgang mit Werten
→ Weitere Informationen zum Unterschied zwischen dem Wert und dem Text eines Felds finden Sie unter Anatomie eines Felds.
Validierungsreihenfolge
Klassenvalidator implementieren
Felder sollten nur bestimmte Werte akzeptieren. Beispielsweise sollten in Zahlenfeldern nur Zahlen und in Farbfeldern nur Farben eingegeben werden können. Dies wird durch klassen- und lokale Validator sichergestellt. Für den Klassenvalidierer gelten dieselben Regeln wie für lokale Validierer, mit der Ausnahme, dass er auch im Konstruktor ausgeführt wird und daher nicht auf den Quellblock verweisen darf.
Wenn Sie den Klassenvalidierer Ihres Felds implementieren möchten, überschreiben Sie die Funktion doClassValidation_
.
doClassValidation_(newValue) {
if (typeof newValue != 'string') {
return null;
}
return newValue;
};
Gültige Werte verarbeiten
Wenn der an ein Feld mit setValue
übergebene Wert gültig ist, erhalten Sie einen doValueUpdate_
-Callback. Standardmäßig gilt für die Funktion doValueUpdate_
Folgendes:
- Die Property
value_
wird aufnewValue
gesetzt. - Die Property
isDirty_
wird auftrue
festgelegt.
Wenn Sie den Wert einfach speichern und keine benutzerdefinierte Verarbeitung vornehmen möchten, müssen Sie doValueUpdate_
nicht überschreiben.
Andernfalls haben Sie folgende Möglichkeiten:
- Benutzerdefinierter Speicherplatz:
newValue
- Andere Attribute basierend auf
newValue
ändern - Speichern Sie, ob der aktuelle Wert gültig ist oder nicht.
Sie müssen doValueUpdate_
überschreiben:
doValueUpdate_(newValue) {
super.doValueUpdate_(newValue);
this.displayValue_ = newValue;
this.isValueValid_ = true;
}
Umgang mit ungültigen Werten
Wenn der an das Feld mit setValue
übergebene Wert ungültig ist, erhalten Sie einen doValueInvalid_
-Callback. Standardmäßig führt die Funktion doValueInvalid_
nichts aus. Das bedeutet, dass ungültige Werte standardmäßig nicht angezeigt werden. Außerdem wird das Feld nicht noch einmal gerendert, da die Eigenschaft isDirty_
nicht festgelegt wird.
Wenn Sie ungültige Werte anzeigen lassen möchten, sollten Sie doValueInvalid_
überschreiben.
In den meisten Fällen sollten Sie für displayValue_
den Wert „ungültig“ festlegen, isDirty_
auf true
setzen und override
render_ aktivieren, damit die Anzeige im Block anhand von displayValue_
statt value_
aktualisiert wird.
doValueInvalid_(newValue) {
this.displayValue_ = newValue;
this.isDirty_ = true;
this.isValueValid_ = false;
}
Mehrteilige Werte
Wenn Ihr Feld einen mehrteiligen Wert enthält (z.B. Listen, Vektoren, Objekte), können Sie festlegen, dass die Teile wie einzelne Werte behandelt werden sollen.
doClassValidation_(newValue) {
if (FieldTurtle.PATTERNS.indexOf(newValue.pattern) == -1) {
newValue.pattern = null;
}
if (FieldTurtle.HATS.indexOf(newValue.hat) == -1) {
newValue.hat = null;
}
if (FieldTurtle.NAMES.indexOf(newValue.turtleName) == -1) {
newValue.turtleName = null;
}
if (!newValue.pattern || !newValue.hat || !newValue.turtleName) {
this.cachedValidatedValue_ = newValue;
return null;
}
return newValue;
}
Im obigen Beispiel wird jedes Attribut von newValue
einzeln geprüft. Wenn dann am Ende der doClassValidation_
-Funktion eine einzelne Property ungültig ist, wird der Wert im Cache der Property cacheValidatedValue_
gespeichert, bevor null
(ungültig) zurückgegeben wird. Wenn das Objekt mit einzeln validierten Eigenschaften im Cache gespeichert wird, kann die Funktion doValueInvalid_
sie separat verarbeiten, indem einfach eine !this.cacheValidatedValue_.property
-Prüfung durchgeführt wird, anstatt jede Eigenschaft einzeln noch einmal zu validieren.
Dieses Muster zur Validierung mehrteiliger Werte kann auch in lokalen Validierungsmethoden verwendet werden. Derzeit gibt es jedoch keine Möglichkeit, dieses Muster durchzusetzen.
isDirty_
isDirty_
ist ein Flag, das in der Funktion setValue
und in anderen Teilen des Felds verwendet wird, um anzugeben, ob das Feld neu gerendert werden muss. Wenn sich der Anzeigewert des Felds geändert hat, sollte isDirty_
normalerweise auf true
gesetzt werden.
Text
→ Informationen dazu, wo der Text eines Felds verwendet wird und wie er sich vom Wert des Felds unterscheidet, finden Sie unter Anatomie eines Felds.
Wenn sich der Text des Felds vom Wert des Felds unterscheidet, sollten Sie die Funktion getText
überschreiben, um den richtigen Text anzugeben.
getText() {
let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
text += ' hat';
}
return text;
}
Mitbearbeiter erstellen
Wenn Sie die Funktion showEditor_
definieren, achtet Blockly automatisch auf Klicks und ruft showEditor_
zum richtigen Zeitpunkt auf. Sie können beliebigen HTML-Code in Ihrem Editor anzeigen, indem Sie ihn in eines der beiden speziellen divs einfügen, DropDownDiv und WidgetDiv, die über der restlichen Blockly-Benutzeroberfläche schweben.
DropDownDiv und WidgetDiv
Mit DropDownDiv
können Sie Editoren in einem Feld bereitstellen, das mit einem Feld verbunden ist. Sie positioniert sich automatisch in der Nähe des Feldes, bleibt aber innerhalb der sichtbaren Grenzen. Die Winkelauswahl und die Farbauswahl sind gute Beispiele für die DropDownDiv
.
Mit WidgetDiv
können Sie Editoren bereitstellen, die nicht in einem Feld angezeigt werden. Bei Zahlenfeldern wird das Feld mit dem WidgetDiv über ein HTML-Texteingabefeld abgedeckt. Das DropDownDiv übernimmt die Positionierung für Sie, das WidgetDiv hingegen nicht. Die Elemente müssen manuell positioniert werden. Das Koordinatensystem ist in Pixelkoordinaten relativ zum linken oberen Fensterrand. Der Editor für die Texteingabe ist ein gutes Beispiel für die WidgetDiv
.
Beispielcode für DropDownDiv
showEditor_() {
// Create the widget HTML
this.editor_ = this.dropdownCreate_();
Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);
// Set the dropdown's background colour.
// This can be used to make it match the colour of the field.
Blockly.DropDownDiv.setColour('white', 'silver');
// Show it next to the field. Always pass a dispose function.
Blockly.DropDownDiv.showPositionedByField(
this, this.disposeWidget_.bind(this));
}
Beispielcode für WidgetDiv
showEditor_() {
// Show the div. This automatically closes the dropdown if it is open.
// Always pass a dispose function.
Blockly.WidgetDiv.show(
this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));
// Create the widget HTML.
var widget = this.createWidget_();
Blockly.WidgetDiv.getDiv().appendChild(widget);
}
Bereinigen
Sowohl das DropDownDiv als auch das WidgetDiv übernehmen das Löschen der HTML-Elemente des Widgets. Alle Ereignis-Listener, die Sie auf diese Elemente angewendet haben, müssen Sie jedoch manuell entfernen.
widgetDispose_() {
for (let i = this.editorListeners_.length, listener;
listener = this.editorListeners_[i]; i--) {
Blockly.browserEvents.unbind(listener);
this.editorListeners_.pop();
}
}
Die Funktion dispose
wird im null
-Kontext auf der DropDownDiv
aufgerufen. Auf dem WidgetDiv
wird es im Kontext des WidgetDiv
aufgerufen. In beiden Fällen ist es am besten, die Funktion bind zu verwenden, wenn Sie eine Dispose-Funktion übergeben, wie in den Beispielen DropDownDiv
und WidgetDiv
oben gezeigt.
→ Informationen zur Entsorgung, die nicht speziell auf die Entsorgung von Editoren bezogen sind, finden Sie unter Entsorgung.
Blockanzeige aktualisieren
Mit der Funktion render_
wird die Blockanzeige des Felds so aktualisiert, dass sie dem internen Wert entspricht.
Beispiele:
- Text ändern (Drop-down-Menü)
- Farbe ändern (color)
Standardeinstellungen
Die Standardfunktion render_
legt den angezeigten Text auf das Ergebnis der Funktion getDisplayText_
fest. Die Funktion getDisplayText_
gibt die value_
-Eigenschaft des Felds zurück, die in einen String umgewandelt wurde, nachdem sie auf die maximale Textlänge gekürzt wurde.
Wenn Sie die Standardanzeige im Block verwenden und das Standardtextverhalten für Ihr Feld funktioniert, müssen Sie render_
nicht überschreiben.
Wenn das Standardtextverhalten für Ihr Feld funktioniert, das Block-Display Ihres Felds aber zusätzliche statische Elemente enthält, können Sie die Standardfunktion render_
aufrufen. Sie müssen sie jedoch trotzdem überschreiben, um die Größe des Felds zu aktualisieren.
Wenn das Standardtextverhalten für Ihr Feld nicht funktioniert oder das On-Block-Display Ihres Felds zusätzliche dynamische Elemente enthält, müssen Sie die Funktion render_
anpassen.
Rendering anpassen
Wenn das Standard-Rendering-Verhalten für Ihr Feld nicht funktioniert, müssen Sie ein benutzerdefiniertes Rendering-Verhalten definieren. Das kann von der Einstellung benutzerdefinierten Anzeigetexts über das Ändern von Bildelementen bis hin zum Aktualisieren von Hintergrundfarben reichen.
Alle Änderungen an DOM-Attributen sind zulässig. Beachten Sie dabei Folgendes:
- Die Erstellung des DOM sollte während der Initialisierung erfolgen, da dies effizienter ist.
- Sie sollten immer die Property „
size_
“ so aktualisieren, dass sie der Größe des On-Block-Displays entspricht.
render_() {
switch(this.value_.hat) {
case 'Stovepipe':
this.stovepipe_.style.display = '';
break;
case 'Crown':
this.crown_.style.display = '';
break;
case 'Mask':
this.mask_.style.display = '';
break;
case 'Propeller':
this.propeller_.style.display = '';
break;
case 'Fedora':
this.fedora_.style.display = '';
break;
}
switch(this.value_.pattern) {
case 'Dots':
this.shellPattern_.setAttribute('fill', 'url(#polkadots)');
break;
case 'Stripes':
this.shellPattern_.setAttribute('fill', 'url(#stripes)');
break;
case 'Hexagons':
this.shellPattern_.setAttribute('fill', 'url(#hexagons)');
break;
}
this.textContent_.nodeValue = this.value_.turtleName;
this.updateSize_();
}
Größe aktualisieren
Das Aktualisieren der size_
-Eigenschaft eines Felds ist sehr wichtig, da sie dem Block-Rendering-Code mitteilt, wie das Feld positioniert werden soll. Am besten finden Sie durch Ausprobieren heraus, wie hoch size_
sein sollte.
updateSize_() {
const bbox = this.movableGroup_.getBBox();
let width = bbox.width;
let height = bbox.height;
if (this.borderRect_) {
width += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
height += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
this.borderRect_.setAttribute('width', width);
this.borderRect_.setAttribute('height', height);
}
// Note how both the width and the height can be dynamic.
this.size_.width = width;
this.size_.height = height;
}
Passende Blockfarben
Wenn Sie möchten, dass die Elemente Ihres Felds mit den Farben des Blocks übereinstimmen, an dem sie angehängt sind, sollten Sie die applyColour
-Methode überschreiben. Sie sollten über das Style-Attribut des Blocks auf die Farbe zugreifen.
applyColour() {
const sourceBlock = this.sourceBlock_;
if (sourceBlock.isShadow()) {
this.arrow_.style.fill = sourceBlock.style.colourSecondary;
} else {
this.arrow_.style.fill = sourceBlock.style.colourPrimary;
}
}
Bearbeitbarkeit aktualisieren
Mit der Funktion updateEditable
können Sie festlegen, wie das Feld angezeigt wird, je nachdem, ob es bearbeitbar ist oder nicht. Die Standardfunktion sorgt dafür, dass der Hintergrund eine Hover-Antwort (Rahmen) hat oder nicht, wenn er bearbeitbar ist oder nicht.
Die Größe der Blockanzeige sollte sich nicht ändern, je nachdem, ob sie bearbeitet werden kann. Alle anderen Änderungen sind jedoch zulässig.
updateEditable() {
if (!this.fieldGroup_) {
// Not initialized yet.
return;
}
super.updateEditable();
const group = this.getClickTarget_();
if (!this.isCurrentlyEditable()) {
group.style.cursor = 'not-allowed';
} else {
group.style.cursor = this.CURSOR;
}
}
Serialisierung
Bei der Speicherung wird der Status des Felds gespeichert, damit es später wieder in den Arbeitsbereich geladen werden kann.
Der Status Ihres Arbeitsbereichs enthält immer den Wert des Felds, kann aber auch andere Status enthalten, z. B. den Status der Benutzeroberfläche des Felds. Wenn Ihr Feld beispielsweise eine zoombare Karte ist, auf der Nutzer Länder auswählen können, können Sie auch die Zoomstufe serialisieren.
Wenn Ihr Feld serialisierbar ist, müssen Sie die Property SERIALIZABLE
auf true
festlegen.
Blockly bietet zwei Serialization Hooks für Felder. Ein Paar Hooks funktioniert mit dem neuen JSON-Serialisierungssystem und das andere Paar mit dem alten XML-Serialisierungssystem.
saveState
und loadState
saveState
und loadState
sind Serialization Hooks, die mit dem neuen JSON-Serialisierungssystem funktionieren.
In einigen Fällen müssen Sie diese nicht angeben, da die Standardimplementierungen funktionieren. Wenn (1) Ihr Feld eine direkte Unterklasse der Basisklasse Blockly.Field
ist, (2) Ihr Wert ein JSON-serialisierbarer Typ ist und (3) Sie den Wert nur serialisieren müssen, funktioniert die Standardimplementierung einwandfrei.
Andernfalls sollte Ihre saveState
-Funktion ein JSON-serialisierbares Objekt/einen JSON-serialisierbaren Wert zurückgeben, der den Status des Felds darstellt. Die loadState
-Funktion sollte dasselbe serialisierbare JSON-Objekt/denselben serialisierbaren JSON-Wert akzeptieren und auf das Feld anwenden.
saveState() {
return {
'country': this.getValue(), // Value state
'zoom': this.getZoomLevel(), // UI state
};
}
loadState(state) {
this.setValue(state['country']);
this.setZoomLevel(state['zoom']);
}
Vollständige Serialization und Sicherung von Daten
saveState
empfängt außerdem den optionalen Parameter doFullSerialization
. Diese Option wird für Felder verwendet, die normalerweise auf einen Zustand verweisen, der von einem anderen Serializer serialisiert wurde (z. B. Back-End-Datenmodelle). Der Parameter signalisiert, dass der referenzierte Status nicht verfügbar sein wird, wenn der Block deserialisiert wird. Daher sollte die gesamte Serialization vom Feld selbst durchgeführt werden. Das ist beispielsweise der Fall, wenn ein einzelner Block serialisiert oder ein Block kopiert und eingefügt wird.
Zwei gängige Anwendungsfälle dafür:
- Wenn ein einzelner Block in einen Arbeitsbereich geladen wird, in dem das zugrunde liegende Datenmodell nicht vorhanden ist, enthält das Feld in seinem eigenen Status genügend Informationen, um ein neues Datenmodell zu erstellen.
- Wenn ein Block kopiert und eingefügt wird, wird für das Feld immer ein neues Datenmodell erstellt, anstatt auf ein vorhandenes zu verweisen.
Ein Beispiel hierfür ist das integrierte Variablenfeld. Normalerweise wird die ID der Variablen serialisiert, auf die verwiesen wird. Wenn doFullSerialization
jedoch wahr ist, wird der gesamte Status serialisiert.
saveState(doFullSerialization) {
const state = {'id': this.variable_.getId()};
if (doFullSerialization) {
state['name'] = this.variable_.name;
state['type'] = this.variable_.type;
}
return state;
}
loadState(state) {
const variable = Blockly.Variables.getOrCreateVariablePackage(
this.getSourceBlock().workspace,
state['id'],
state['name'], // May not exist.
state['type']); // May not exist.
this.setValue(variable.getId());
}
So wird sichergestellt, dass bei der Datenaufnahme in einen Arbeitsbereich, in dem die Variable nicht vorhanden ist, eine neue Variable erstellt werden kann, auf die verwiesen werden kann.
toXml
und fromXml
toXml
und fromXml
sind Serialization Hooks, die mit dem alten XML-Serialisierungssystem funktionieren. Verwende diese Hooks nur, wenn es unbedingt notwendig ist (z. B. wenn du an einer alten Codebasis arbeitest, die noch nicht migriert wurde). Verwende ansonsten saveState
und loadState
.
Die toXml
-Funktion sollte einen XML-Knoten zurückgeben, der den Status des Felds darstellt. Die fromXml
-Funktion sollte denselben XML-Knoten akzeptieren und auf das Feld anwenden.
toXml(fieldElement) {
fieldElement.textContent = this.getValue();
fieldElement.setAttribute('zoom', this.getZoomLevel());
return fieldElement;
}
fromXml(fieldElement) {
this.setValue(fieldElement.textContent);
this.setZoomLevel(fieldElement.getAttribute('zoom'));
}
Bearbeitbare und serialisierbare Properties
Mit der Property EDITABLE
wird festgelegt, ob das Feld eine Benutzeroberfläche haben soll, die angibt, dass damit interagiert werden kann. Der Standardwert ist true
.
Die Property SERIALIZABLE
gibt an, ob das Feld serialisiert werden soll. Der Standardwert ist false
. Wenn diese Eigenschaft true
ist, müssen Sie möglicherweise Funktionen zum Serialisieren und Deserialisieren angeben (siehe Serialisierung).
Cursor anpassen
Mit der Property CURSOR
wird der Cursor festgelegt, der angezeigt wird, wenn Nutzer den Mauszeiger auf Ihr Feld bewegen. Es muss ein gültiger CSS-Cursor-String sein. Standardmäßig ist dies der von .blocklyDraggable
definierte Cursor, der Cursor zum Verschieben.