Eseguire l'upgrade di un campo personalizzato

A luglio 2019 (release 2.20190722) è stata aggiunta un'API dei campi più codificata. È progettato per essere il più compatibile possibile con le versioni precedenti. Ciò significa che se hai creato un campo personalizzato prima di luglio 2019, molto probabilmente continuerà a funzionare. Prima di decidere se è necessario eseguire l'upgrade del campo personalizzato, leggi la sezione Aree di pericolo ed esegui un test approfondito del campo.

Poiché prima di luglio 2019 non esisteva una standardizzazione tra i campi, è difficile coprire tutte le modifiche che uno sviluppatore potrebbe dover apportare. Questo documento cerca di coprire tutte le modifiche probabili, ma se non copre qualcosa che ti interessa, leggi la sezione su come ottenere assistenza per l'upgrade.

Aree pericolose

Le aree pericolose sono luoghi noti in cui l'API è cambiata e il tuo campo potrebbe non funzionare.

Blockly.Field.register

I campi non vengono più registrati tramite Blockly.Field.register();. Ora esiste uno spazio dei nomi fieldRegistry che gestisce la registrazione.

Blockly.Field.register('my_field_name', myFieldClass);

Diventa:

Blockly.fieldRegistry.register('my_field_name', myFieldClass);

setText

La funzione setText non viene più chiamata dal core di Blockly, quindi se la tua funzione setText contiene logica, dovrà essere spostata nella suite di funzioni di gestione dei valori, nella funzione getText e nelle funzioni di rendering (a seconda di cosa fa esattamente la funzione setText).

CustomFields.UpgradeField.prototype.setText = function(newText) {
  // Do validation.
  if (typeof newText != 'string' || newText === this.text_) {
    return;
  }

  // Fire event.
  if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
    Blockly.events.fire(new Blockly.Events.BlockChange(
        this.sourceBlock_, 'field', this.name, this.text_, newText
    ));
  }

  // Update text value.
  this.text_ = 'prefix' + newText;

  // Rerender.
  this.size_.width = 0;
};

Diventa:

CustomFields.UpgradeField.prototype.doClassValidation_ = function(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

CustomFields.UpgradeField.prototype.getText = function() {
  return  'prefix' + this.value_;
}

Blockly gestisce automaticamente:

  • Verifica se il nuovo valore è diverso da quello precedente.
  • Aggiornamento del valore in corso.
  • Attivazione di eventi di modifica.
  • Rendering del campo.

Dovrai gestire:

Gli upgrade consigliati sono i punti in cui l'API Field è stata modificata, ma se scegli di non apportare modifiche, il campo continuerà a funzionare.

SERIALIZZABILE

Per ulteriori informazioni sulle proprietà EDITABLE e SERIALIZABLE, vedi Proprietà modificabili e serializzabili.

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

L'avviso riportato di seguito può essere ignorato, ma puoi risolverlo definendo la proprietà SERIALIZABLE:

Detected an editable field that was not serializable. Please define
SERIALIZABLE property as true on all editable custom fields. Proceeding
with serialization.

L'avviso riportato sopra indica che Blockly ritiene che tu voglia serializzare il campo (perché la proprietà EDITABLE è true), ma non può esserne certo finché non definisci la proprietà SERIALIZABLE. Se scegli di lasciare tutto così, tutto funzionerà correttamente e il campo verrà serializzato, ma riceverai avvisi nella console.

size_.width

this.size_.width = 0;

Diventa:

this.isDirty_ = true;

L'avviso riportato di seguito può essere ignorato, ma puoi risolverlo impostando la proprietà isDirty_ anziché la proprietà size_.width:

Deprecated use of setting size_.width to 0 to rerender a field. Set
field.isDirty_ to true instead.

L'avviso riportato sopra indica che Blockly ha rilevato che stai utilizzando un metodo precedente per il rendering di un campo e ti invita a utilizzare il nuovo metodo.

Per ulteriori informazioni sulla proprietà isDirty_, vedi isDirty_.

init

La funzione init è stata trasformata in una funzione modello per ridurre il codice duplicato nelle sottoclassi.

CustomFields.UpgradeField.prototype.init = function() {
  if (this.fieldGroup_) {
    // Already initialized once.
    return;
  }

  // Call superclass.
  CustomFields.UpgradeField.superClass_.init.call(this);

  // Create DOM elements.
  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);

  // Bind events.
  this.mouseOverWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);

  // Render.
  this.setValue(this.getValue());
};

Diventa:

CustomFields.UpgradeField.prototype.initView = function() {
  CustomFields.UpgradeField.superClass_.initView.call(this);

  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);
};

CustomFields.UpgradeField.prototype.bindEvents_ = function() {
  CustomFields.UpgradeField.superClass_.bindEvents_.call(this);

  this.mouseOverWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);
};

Ciò significa che Blockly ora gestisce automaticamente:

  • Verifica se il campo è già inizializzato.
  • Creazione di fieldGroup_ in corso.
  • Rendering del campo.
  • Descrizione comando di binding e visualizzazione degli eventi dell'editor.

Dovrai gestire:

onMouseDown_

CustomFields.UpgradeField.prototype.onMouseDown_ = function(e) {
  // ...
};

Diventa:

CustomFields.UpgradeField.prototype.showEditor_ = function() {
  // ...
}

Ti consigliamo di eseguire l'override della funzione showEditor_ per gestire i clic del mouse anziché la funzione onMouseDown_, in quanto ciò consente all'input di passare attraverso il sistema di gesti.

Per ulteriori informazioni sugli editor, consulta Editor.

setValue

La funzione setValue è ora una funzione modello per ridurre il codice duplicato nelle sottoclassi. Se la funzione setValue contiene logica, valuta la possibilità di eseguire il refactoring in modo che si adatti ai percorsi di gestione dei valori descritti in Gestione dei valori.

text_

Ti consigliamo di non accedere o aggiornare mai direttamente la proprietà text_ del tuo campo. Utilizza invece la funzione getText per accedere al testo leggibile del campo e la funzione setValue per aggiornare il valore memorizzato del campo.

Per ulteriori informazioni sul valore di un campo rispetto al relativo testo, consulta Anatomia di un campo.

Ricevere assistenza per l'upgrade

Cosa fornire

Quando richiedi assistenza, è meglio porre domande specifiche:

Sconsigliato: "Qual è il problema con questo campo?"

Inoltre, non è consigliabile utilizzare "Aiutami ad aggiornare questo campo".

Consigliato: "Il testo del campo non viene aggiornato correttamente".

È inoltre necessario fornire risorse alle persone che ti assistono. Questi file devono essere facili da usare per gli altri.

Opzione non consigliata:

  • Immagini di codice.
  • Codice incompleto.

Consigliato:

  • Completa il codice campo in formato di testo.
  • Immagini di GIF di comportamenti scorretti in campo.
  • Passaggi per riprodurre il comportamento errato del campo.
  • La versione di Blockly da cui stai eseguendo l'upgrade.

Dove pubblicare

Pubblica le domande sull'upgrade nel forum per gli sviluppatori di Blockly.

Se hai la certezza che il problema riguarda il core di Blockly, puoi anche pubblicare una segnalazione su GitHub di Blockly. Se decidi di segnalare un problema, compila tutte le informazioni richieste.