Uaktualnianie pola niestandardowego

W lipcu 2019 r. (wersja 2.20190722) dodaliśmy bardziej skodyfikowany interfejs API pól. Ma on być w jak największym stopniu zgodny wstecznie. Oznacza to, że jeśli przed lipcem 2019 r. utworzono pole niestandardowe, najprawdopodobniej będzie ono nadal działać. Zanim zdecydujesz, czy Twoje pole niestandardowe wymaga uaktualnienia, przeczytaj sekcję Obszary ryzyka i dokładnie przetestuj pole.

Przed lipcem 2019 r. nie było standardów dotyczących pól, dlatego trudno jest uwzględnić wszystkie zmiany, które deweloper może musieć wprowadzić. Ten dokument zawiera wszystkie prawdopodobne zmiany, ale jeśli nie obejmuje on czegoś, co Cię interesuje, przeczytaj sekcję dotyczącą uzyskiwania pomocy przy uaktualnianiu.

Strefy zagrożenia

Obszary zagrożenia to znane miejsca, w których interfejs API uległ zmianie, a Twoje pole może być uszkodzone.

Blockly.Field.register

Pola nie są już rejestrowane za pomocą Blockly.Field.register();. Obecnie rejestracją zajmuje się przestrzeń nazw fieldRegistry.

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

Zmienia się w:

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

setText

Funkcja setText nie jest już wywoływana przez rdzeń Blockly, więc jeśli zawiera logikę, musisz ją przenieść do pakietu funkcji obsługi wartości, funkcji getTextfunkcji renderowania (w zależności od tego, co dokładnie robi funkcja setText).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;
};

Zmienia się w:

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

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

Blockly automatycznie obsługuje:

  • Sprawdzanie, czy nowa wartość różni się od starej.
  • Aktualizuję wartość.
  • wywoływanie zdarzeń zmiany,
  • ponowne renderowanie pola.

Musisz zadbać o:

Zalecane uaktualnienia to miejsca, w których interfejs API pola został zmieniony, ale jeśli nie wprowadzisz zmian, pole najprawdopodobniej nadal będzie działać.

SERIALIZABLE

Więcej informacji o właściwościach EDITABLESERIALIZABLE znajdziesz w artykule Właściwości, które można edytować i serializować.

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

Poniższe ostrzeżenie można zignorować, ale możesz je rozwiązać, definiując właściwość SERIALIZABLE:

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

Powyższy komunikat ostrzegawczy oznacza, że Blockly uważa, że chcesz serializować pole (ponieważ właściwość EDITABLE ma wartość true), ale nie może mieć pewności, dopóki nie zdefiniujesz właściwości SERIALIZABLE. Jeśli nie zmienisz tego ustawienia, wszystko będzie działać prawidłowo, a pole zostanie serializowane, ale w konsoli będą się pojawiać ostrzeżenia.

size_.width

this.size_.width = 0;

Zmienia się w:

this.isDirty_ = true;

Poniższe ostrzeżenie można zignorować, ale możesz je rozwiązać, ustawiając właściwość isDirty_ zamiast właściwości size_.width:

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

Powyższe ostrzeżenie oznacza, że Blockly wykrył, że używasz starej metody ponownego renderowania pola, i zachęca do użycia nowej metody.

Więcej informacji o właściwości isDirty_ znajdziesz w artykule isDirty_.

init

Funkcja init została przekształcona w funkcję szablonu, aby ograniczyć powielanie kodu w podklasach.

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());
};

Zmienia się w:

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_);
};

Oznacza to, że Blockly automatycznie obsługuje teraz:

  • Sprawdzanie, czy pole zostało już zainicjowane.
  • Tworzę fieldGroup_.
  • renderowanie pola,
  • Wiązanie etykietki i wyświetlanie zdarzeń edytora.

Musisz zadbać o:

onMouseDown_

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

Zmienia się w:

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

Zalecamy zastąpienie funkcji showEditor_ funkcją obsługującą kliknięcia myszą zamiast funkcji onMouseDown_, ponieważ umożliwia to przekazywanie danych wejściowych przez system gestów.

Więcej informacji o edytorach znajdziesz w sekcji Edytorzy.

setValue

Funkcja setValue jest teraz funkcją szablonu, co pozwala ograniczyć powielanie kodu w podklasach. Jeśli funkcja setValue zawiera logikę, rozważ jej refaktoryzację, aby pasowała do ścieżek obsługi wartości opisanych w sekcji Obsługa wartości.

text_

Zalecamy, aby nigdy nie uzyskiwać dostępu do właściwości text_ pola ani jej bezpośrednio nie aktualizować. Zamiast tego użyj funkcji getTextsetValue, aby uzyskać dostęp do tekstu pola czytelnego dla użytkownika, oraz funkcji setValue, aby zaktualizować przechowywaną wartość pola.

Więcej informacji o wartości i tekście pola znajdziesz w artykule Anatomia pola.

Uzyskiwanie pomocy dotyczącej przejścia na wyższą wersję

Co należy podać

Gdy prosisz o pomoc, najlepiej zadawać konkretne pytania:

Niezalecane: „Co jest nie tak z tym polem?”

Nie zalecamy też używania polecenia „Pomóż mi ulepszyć to pole”.

Zalecane: „Tekst pola nie jest prawidłowo aktualizowany”.

Konieczne jest również udostępnienie zasobów osobom, które Ci pomagają. Te pliki powinny być łatwe w użyciu dla innych osób.

Niezalecane:

  • zdjęcia kodu;
  • Niepełny kod.

Zalecane:

  • Uzupełnij kod pola w formacie tekstowym.
  • Obrazy GIF przedstawiające nieprawidłowe działanie w polu.
  • Kroki umożliwiające odtworzenie nieprawidłowego działania pola.
  • Wersja Blockly, z której uaktualniasz.

Gdzie opublikować

Pytania dotyczące uaktualnienia możesz zadawać na forum dla deweloperów Blockly.

Jeśli masz pewność, że problem dotyczy podstawowej wersji Blockly, możesz też zgłosić problem na GitHubie Blockly. Jeśli zdecydujesz się opublikować problem, podaj wszystkie wymagane informacje.