Nâng cấp trường tuỳ chỉnh

Vào tháng 7 năm 2019 (bản phát hành 2.20190722), chúng tôi đã thêm một API trường được mã hoá nhiều hơn. Mục đích của việc này là để có khả năng tương thích ngược cao nhất có thể. Điều này có nghĩa là nếu bạn đã tạo một trường tuỳ chỉnh trước tháng 7 năm 2019, thì trường đó có thể sẽ tiếp tục hoạt động. Trước khi quyết định có cần nâng cấp trường tuỳ chỉnh hay không, bạn nên đọc kỹ phần Khu vực nguy hiểm và kiểm tra kỹ lưỡng trường của mình.

Vì các trường không được chuẩn hoá trước tháng 7 năm 2019, nên rất khó để bao gồm tất cả những thay đổi mà nhà phát triển có thể cần thực hiện. Tài liệu này cố gắng đề cập đến tất cả những thay đổi có thể xảy ra. Tuy nhiên, nếu tài liệu này không đề cập đến nội dung mà bạn quan tâm, vui lòng đọc phần về nhận trợ giúp nâng cấp.

Khu vực nguy hiểm

Các vùng nguy hiểm là những nơi đã biết mà API đã thay đổi và trường của bạn có thể bị hỏng.

Blockly.Field.register

Các trường không còn được đăng ký thông qua Blockly.Field.register(); nữa. Hiện có một không gian tên fieldRegistry xử lý việc đăng ký.

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

Trở thành:

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

setText

Hàm setText không còn được lõi Blockly gọi nữa, vì vậy, nếu hàm setText của bạn chứa logic, thì bạn sẽ cần phải di chuyển hàm đó sang bộ hàm xử lý giá trị, hàm getTexthàm kết xuất (tuỳ thuộc vào chính xác những gì hàm setText của bạn đang thực hiện).

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

Trở thành:

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

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

Blockly tự động xử lý:

  • Kiểm tra xem giá trị mới có khác với giá trị cũ hay không.
  • Đang cập nhật giá trị.
  • Kích hoạt các sự kiện thay đổi.
  • Kết xuất lại trường.

Bạn sẽ cần xử lý:

Nâng cấp được đề xuất là những nơi mà API trường đã thay đổi, nhưng nếu bạn chọn không thực hiện thay đổi, thì trường của bạn có thể vẫn hoạt động.

SERIALIZABLE

Để biết thêm thông tin về các thuộc tính EDITABLESERIALIZABLE, hãy xem Các thuộc tính có thể chỉnh sửa và có thể chuyển đổi tuần tự.

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

Bạn có thể bỏ qua cảnh báo bên dưới, nhưng bạn có thể giải quyết cảnh báo này bằng cách xác định thuộc tính SERIALIZABLE:

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

Cảnh báo trên có nghĩa là Blockly cho rằng bạn muốn trường được chuyển đổi tuần tự (vì thuộc tính EDITABLE là true), nhưng không thể chắc chắn cho đến khi bạn xác định thuộc tính SERIALIZABLE. Nếu bạn chọn giữ nguyên, mọi thứ sẽ hoạt động bình thường và trường của bạn sẽ được chuyển đổi tuần tự, nhưng bạn sẽ nhận được cảnh báo trên bảng điều khiển.

size_.width

this.size_.width = 0;

Trở thành:

this.isDirty_ = true;

Bạn có thể bỏ qua cảnh báo bên dưới, nhưng bạn có thể giải quyết cảnh báo này bằng cách đặt thuộc tính isDirty_ thay vì thuộc tính size_.width:

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

Cảnh báo ở trên có nghĩa là Blockly đã phát hiện thấy bạn đang sử dụng một phương thức cũ để kết xuất lại một trường và muốn bạn sử dụng phương thức mới.

Để biết thêm thông tin về thuộc tính isDirty_, hãy xem isDirty_.

init

Hàm init đã được chuyển thành một hàm mẫu để giảm mã trùng lặp trong các lớp con.

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

Trở thành:

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

Điều này có nghĩa là Blockly hiện tự động xử lý:

  • Kiểm tra xem trường đã được khởi tạo hay chưa.
  • Đang tạo fieldGroup_.
  • Kết xuất trường.
  • Liên kết chú thích và hiển thị các sự kiện của trình chỉnh sửa.

Bạn sẽ cần xử lý:

onMouseDown_

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

Trở thành:

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

Bạn nên ghi đè hàm showEditor_ để xử lý các lần nhấp chuột thay vì hàm onMouseDown_ vì hàm này cho phép dữ liệu đầu vào truyền qua hệ thống cử chỉ.

Để biết thêm thông tin về người chỉnh sửa, hãy xem phần Người chỉnh sửa.

setValue

Hàm setValue hiện là một hàm mẫu để giảm mã trùng lặp trong các lớp con. Nếu hàm setValue của bạn có chứa logic, hãy cân nhắc việc tái cấu trúc hàm đó để phù hợp với các đường dẫn xử lý giá trị được mô tả trong phần Xử lý giá trị.

text_

Bạn không bao giờ nên truy cập hoặc cập nhật trực tiếp thuộc tính text_ của trường. Thay vào đó, hãy dùng hàm getText để truy cập vào văn bản mà người dùng có thể đọc của trường và hàm setValue để cập nhật giá trị đã lưu trữ của trường.

Để biết thêm thông tin về giá trị của một trường so với văn bản của trường đó, hãy xem phần Kết cấu của một trường.

Nhận trợ giúp nâng cấp

Thông tin cần cung cấp

Khi yêu cầu trợ giúp, bạn nên đặt những câu hỏi cụ thể:

Không nên: "Trường này có vấn đề gì?"

Bạn cũng không nên sử dụng câu lệnh "Giúp tôi nâng cấp trường này".

Đề xuất: "Văn bản trong trường không cập nhật đúng cách".

Bạn cũng cần cung cấp nguồn lực cho những người hỗ trợ bạn. Người khác có thể dễ dàng sử dụng những tệp này.

Không nên:

  • Hình ảnh về mã.
  • Mã chưa hoàn chỉnh.

Được đề xuất:

  • Mã trường hoàn chỉnh ở định dạng văn bản.
  • Hình ảnh về ảnh GIF có hành vi xấu trên sân.
  • Các bước tái hiện hành vi không phù hợp của trường.
  • Phiên bản Blockly mà bạn đang nâng cấp.

Nơi đăng

Đăng câu hỏi về việc nâng cấp trên diễn đàn nhà phát triển Blockly.

Nếu chắc chắn rằng vấn đề là do lõi Blockly, bạn cũng có thể đăng vấn đề trên GitHub của Blockly. Nếu bạn quyết định đăng vấn đề, vui lòng điền tất cả thông tin được yêu cầu.