Uaktualnianie pola niestandardowego

W lipcu 2019 r. (wersja 2.20190722) dodaliśmy interfejs API bardziej ujednoliconych pól. Jego zadaniem jest zapewnienie jak największej zgodności wstecznej. Oznacza to, że jeśli pole niestandardowe zostało utworzone przed lipcem 2019 r., najprawdopodobniej będzie ono nadal działać. Przed podjęciem decyzji o uaktualnieniu pola niestandardowego przeczytaj sekcję Obszary zagrożeń i przeprowadź dokładne testy.

Przed lipcem 2019 roku mieliśmy brak standaryzacji między polami, dlatego ciężko jest uwzględnić wszystkie zmiany, które mogą być wprowadzone przez dewelopera. Ten dokument zawiera opis wszystkich prawdopodobnych zmian, ale jeśli nie zawiera on informacji, które Cię interesują, przeczytaj sekcję o uzyskaniu pomocy z przejściem na nowszą wersję.

Obszary niebezpieczne

Obszary zagrożone 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 do Blockly.Field.register();. Istnieje teraz przestrzeń nazw FieldRegistry, która obsługuje rejestrację.

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

Staje się:

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

setText

Funkcja setText nie jest już wywoływana przez rdzenie Blockly, dlatego jeśli Twoja funkcja setText zawiera logikę, trzeba ją przenieść do zestawu funkcji do obsługi wartości, funkcji getText i funkcji renderowania (w zależności od tego, co dokładnie robi funkcja 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;
};

Staje się:

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:

  • Sprawdzam, czy nowa wartość różni się od poprzedniej.
  • Aktualizuję wartość.
  • Uruchamiam zdarzenia zmiany.
  • Ponownie renderuję pole.

Przygotuj się na:

Zalecane uaktualnienia to miejsca, w których zmienił się interfejs API pól, ale jeśli nie wprowadzisz zmian, Twoje pole najprawdopodobniej nadal będzie działać.

SERIALIZOWANE

Więcej informacji o właściwościach EDITABLE i SERIALIZABLE znajdziesz w artykule o właściwościach z możliwością edytowania i serializacji.

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

Poniższe ostrzeżenie jest ignorowane, 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ższe ostrzeżenie oznacza, że Blockly uważasz, że chcesz, aby pole zostało zserializowane (ponieważ właściwość EDITABLE ma wartość prawda), ale nie możesz mieć pewności, że chcesz ją zdefiniować, dopóki nie zdefiniujesz właściwości SERIALIZABLE. Jeśli zostawisz to ustawienie bez zmian, wszystko będzie działać prawidłowo, a pole zostanie zserializowane, ale będziesz otrzymywać ostrzeżenia w konsoli.

size_.width

this.size_.width = 0;

Staje się:

this.isDirty_ = true;

Poniższe ostrzeżenie jest ignorowane, 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ło, że używasz starej metody ponownego renderowania pola i chcesz użyć nowej.

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

init

Funkcja init została przekształcona w funkcję szablonu, aby ograniczyć duplikat kodu w klasach podrzędnych.

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

Staje się:

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 obsługuje teraz automatycznie:

  • Sprawdzam, czy pole zostało już zainicjowane.
  • Tworzę fieldGroup_.
  • Renderuję pole.
  • Etykietka powiązania i pokaż zdarzenia edytora.

Przygotuj się na:

onMouseDown_

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

Staje się:

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

Zalecamy zastąpienie funkcji showEditor_ do obsługi kliknięć myszą, a nie funkcji onMouseDown_, ponieważ umożliwia ona przekazywanie danych przez system gestów.

Więcej informacji na temat edytorów znajdziesz w artykule Edytujący.

setValue

Funkcja setValue jest teraz funkcją szablonu, która ogranicza zduplikowany kod w podklasach. Jeśli funkcja setValue zawiera logikę, rozważ jej refaktoryzację, aby dopasować ją 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 nie aktualizować. Zamiast tego użyj funkcji getText, aby uzyskać dostęp do czytelnego dla użytkownika tekstu w polu, i funkcji setValue, aby zaktualizować zapisaną wartość pola.

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

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

Co podać

Gdy prosisz o pomoc, najlepiej zadaj konkretne pytania:

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

Niezalecane też: „Pomóż mi uaktualnić to pole”.

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

Niezbędne jest też udostępnienie zasobów osobom, które chcą Ci pomóc. Pliki te powinny być łatwe w użyciu.

Niezalecane:

  • Obrazy kodu.
  • Niekompletny kod.

Zalecane:

  • Uzupełnij kod pola w formacie tekstowym.
  • Obrazy GIF przedstawiające niewłaściwe zachowanie pól.
  • Czynności umożliwiające odtworzenie nieprawidłowego działania pól.
  • Wersja Blockly, którą uaktualniasz.

Gdzie publikować

Zadaj pytania na temat uaktualnienia na forum dla programistów blokujących.

Jeśli masz pewność, że problem jest związany z blockly core, możesz też opublikować problem na blokowym GitHubie. Jeśli zdecydujesz się zgłosić problem, podaj wszystkie wymagane informacje.