Tạo loại trường mới

Trước khi tạo loại trường mới, hãy cân nhắc xem có một trong loại trường khác phương thức để tuỳ chỉnh các trường cho phù hợp với nhu cầu của bạn. Nếu ứng dụng của bạn cần lưu trữ loại giá trị mới hoặc bạn muốn tạo giao diện người dùng mới cho một loại giá trị hiện có, có thể cần tạo một loại trường mới.

Để tạo trường mới, hãy làm như sau:

  1. Triển khai hàm khởi tạo.
  2. Đăng ký khoá JSON và triển khai fromJson.
  3. Xử lý việc khởi chạy sự kiện và giao diện người dùng trên khối .
  4. Xử lý việc loại bỏ trình nghe sự kiện (Xử lý giao diện người dùng được xử lý cho bạn).
  5. Triển khai việc xử lý giá trị.
  6. Thêm phần văn bản trình bày giá trị của trường để tăng khả năng tiếp cận.
  7. Thêm chức năng bổ sung như:
  8. Định cấu hình các khía cạnh khác của trường, chẳng hạn như:

Phần này giả định rằng bạn đã đọc và quen thuộc với nội dung trong Cấu tạo của Trường.

Để xem ví dụ về trường tùy chỉnh, hãy xem bài viết Trường tùy chỉnh bản minh hoạ của Google.

Triển khai hàm khởi tạo

Hàm khởi tạo của trường chịu trách nhiệm thiết lập giá trị ban đầu của trường và tuỳ ý thiết lập một kênh trình xác thực. Tùy chỉnh hàm khởi tạo của trường được gọi trong quá trình khởi tạo khối nguồn bất kể về việc khối nguồn được xác định trong JSON hay JavaScript. Vì vậy, tùy chỉnh không có quyền truy cập vào khối nguồn trong quá trình tạo.

Mã mẫu sau đây sẽ tạo một trường tuỳ chỉnh có tên là GenericField:

class GenericField extends Blockly.Field {
  constructor(value, validator) {
    super(value, validator);

    this.SERIALIZABLE = true;
  }
}

Chữ ký của phương thức

Hàm khởi tạo trường thường lấy một giá trị và một trình xác thực cục bộ. Giá trị là không bắt buộc và nếu bạn không chuyển giá trị (hoặc bạn chuyển giá trị không vượt qua được lớp xác thực) thì giá trị mặc định của lớp cấp cao sẽ được sử dụng. Đối với Field mặc định thì giá trị đó là null. Nếu bạn không muốn chế độ cài đặt mặc định đó giá trị, sau đó hãy đảm bảo chuyển giá trị phù hợp. Thông số trình xác thực chỉ có trong các trường có thể chỉnh sửa và thường được đánh dấu là không bắt buộc. Tìm hiểu thêm về trình xác thực trong phần Trình xác thực docs.

Cấu trúc

Logic bên trong hàm khởi tạo phải tuân theo luồng sau:

  1. Gọi hàm khởi tạo cấp cao kế thừa (tất cả các trường tuỳ chỉnh đều phải kế thừa từ Blockly.Field hoặc một trong các lớp con của lớp này) để khởi tạo giá trị đúng cách rồi đặt trình xác thực cục bộ cho trường của bạn.
  2. Nếu trường của bạn theo tuần tự, hãy đặt thuộc tính tương ứng trong hàm khởi tạo. Các trường có thể chỉnh sửa phải theo tuần tự và các trường có thể chỉnh sửa được theo mặc định, do đó bạn nên đặt thuộc tính này thành true trừ phi bạn biết video không được chuyển đổi tuần tự.
  3. Không bắt buộc: Áp dụng chế độ tuỳ chỉnh bổ sung (ví dụ: Các trường nhãn cho phép truyền một lớp css, sau đó áp dụng lớp này cho văn bản).

JSON và việc đăng ký

Trong khối JSON định nghĩa, được mô tả bằng một chuỗi (ví dụ: field_number, field_textinput). Blockly duy trì bản đồ từ các chuỗi này đến các đối tượng trường và gọi fromJson trên đối tượng thích hợp trong quá trình tạo.

Gọi Blockly.fieldRegistry.register để thêm loại trường của bạn vào bản đồ này, truyền vào lớp trường làm đối số thứ hai:

Blockly.fieldRegistry.register('field_generic', GenericField);

Bạn cũng cần xác định hàm fromJson. Việc triển khai của bạn nên huỷ tham chiếu trước bất kỳ chuỗi nào bảng tham chiếu đang sử dụng replaceMessageReferences, rồi truyền các giá trị đến hàm khởi tạo.

GenericField.fromJson = function(options) {
  const value = Blockly.utils.parsing.replaceMessageReferences(
      options['value']);
  return new CustomFields.GenericField(value);
};

Đang khởi tạo

Về cơ bản, khi trường của bạn được tạo dựng, trường đó chỉ chứa một giá trị. Khởi tạo là nơi tạo DOM, mô hình được xây dựng (nếu trường sở hữu mô hình) và các sự kiện bị ràng buộc.

Bật tính năng hiển thị

Trong quá trình khởi chạy, bạn chịu trách nhiệm tạo mọi thứ bạn cần cho màn hình trên khối của trường.

Chế độ mặc định, nền và văn bản

Hàm initView mặc định tạo ra một phần tử rect có màu sáng và một phần tử Phần tử text. Nếu bạn muốn trường của mình có cả hai thuộc tính này, cộng thêm một số thuộc tính rất tốt, hãy gọi hàm lớp cấp cao initView trước khi thêm phần còn lại của Các phần tử DOM. Nếu bạn muốn trường của mình có một chứ không phải cả hai, bạn có thể dùng hàm createBorderRect_ hoặc createTextElement_.

Tuỳ chỉnh cấu trúc DOM

Nếu trường của bạn là trường văn bản chung (ví dụ: Văn bản Đầu vào), Quá trình xây dựng DOM sẽ được xử lý cho bạn. Nếu không, bạn sẽ phải ghi đè hàm initView để tạo các phần tử DOM mà bạn sẽ cần trong kết xuất trường của bạn trong tương lai.

Ví dụ: một trường thả xuống có thể chứa cả hình ảnh và văn bản. Trên initView, tạo một thành phần hình ảnh và một thành phần văn bản. Sau đó, trong khoảng thời gian render_ phần tử này sẽ hiển thị phần tử đang hoạt động và ẩn phần tử còn lại, dựa trên loại phần tử tùy chọn.

Bạn có thể tạo các phần tử DOM bằng cách sử dụng Blockly.utils.dom.createSvgElement hoặc sử dụng phương thức tạo DOM truyền thống .

Các yêu cầu hiển thị trên khối của một trường là:

  • Tất cả các phần tử DOM phải là phần tử con của fieldGroup_ của trường. Trường được tạo tự động.
  • Tất cả các phần tử DOM phải nằm trong các phương diện được báo cáo của trường này.

Xem Kết xuất để biết thêm thông tin chi tiết về cách tuỳ chỉnh và cập nhật chế độ hiển thị trên khối.

Thêm biểu tượng văn bản

Nếu bạn muốn thêm biểu tượng vào văn bản của một trường (chẳng hạn như Góc biểu tượng độ của trường) bạn có thể nối thêm phần tử biểu tượng (thường có trong <tspan>) trực tiếp đến textElement_ của trường.

Sự kiện nhập

Theo mặc định, các trường sẽ đăng ký sự kiện chú thích và sự kiện di chuột xuống (được dùng cho đang hiển thị editor). Nếu bạn muốn theo dõi các loại sự kiện khác (ví dụ: nếu bạn muốn xử lý kéo trên một trường), bạn nên ghi đè hàm bindEvents_ của trường đó.

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

Để liên kết với một sự kiện, bạn thường nên sử dụng Blockly.utils.browserEvents.conditionalBind . Phương pháp liên kết sự kiện này sẽ lọc ra các thao tác chạm phụ trong khoảng thời gian kéo. Nếu bạn muốn trình xử lý của mình chạy ngay cả giữa quá trình kéo đang diễn ra bạn có thể sử dụng Blockly.browserEvents.bind .

Vứt bỏ

Nếu bạn đã đăng ký bất kỳ trình nghe sự kiện tuỳ chỉnh nào trong bindEvents_ của trường này bạn cần huỷ đăng ký trong hàm dispose.

Nếu bạn đã khởi chạy chính xác chế độ xem của trường (bằng cách thêm tất cả các phần tử DOM vào fieldGroup_), thì phần tử DOM của trường sẽ được xử lý tự động.

Xử lý giá trị

→ Để biết 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 Cấu trúc của .

Thứ tự xác thực

Sơ đồ quy trình mô tả thứ tự chạy trình xác thực

Triển khai trình xác thực lớp

Các trường chỉ được chấp nhận một số giá trị nhất định. Ví dụ: trường số chỉ nên chấp nhận số, trường màu chỉ chấp nhận màu, v.v. Điều này được đảm bảo thông qua lớp học và địa phương trình xác thực. Lớp trình xác thực tuân theo các quy tắc giống như trình xác thực cục bộ ngoại trừ việc trình xác thực cũng chạy trong hàm khởi tạo và do đó, nó không nên tham chiếu đến khối nguồn.

Để triển khai trình xác thực lớp cho trường của bạn, hãy ghi đè doClassValidation_ .

doClassValidation_(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

Xử lý các giá trị hợp lệ

Nếu giá trị được truyền vào trường có setValue hợp lệ, bạn sẽ nhận được Lệnh gọi lại doValueUpdate_. Theo mặc định, hàm doValueUpdate_:

  • Đặt thuộc tính value_ thành newValue.
  • Thiết lập isDirty_ vào true.

Nếu bạn chỉ cần lưu trữ giá trị và không muốn thực hiện bất kỳ xử lý tuỳ chỉnh nào, bạn không cần ghi đè doValueUpdate_.

Ngược lại, nếu bạn muốn làm những việc như:

  • Bộ nhớ tuỳ chỉnh của newValue.
  • Thay đổi các thuộc tính khác dựa trên newValue.
  • Lưu xem giá trị hiện tại có hợp lệ hay không.

Bạn sẽ cần ghi đè doValueUpdate_:

doValueUpdate_(newValue) {
  super.doValueUpdate_(newValue);
  this.displayValue_ = newValue;
  this.isValueValid_ = true;
}

Xử lý các giá trị không hợp lệ

Nếu giá trị được chuyển vào trường có setValue không hợp lệ, bạn sẽ nhận được Lệnh gọi lại doValueInvalid_. Theo mặc định, hàm doValueInvalid_ thực hiện không có gì. Điều này có nghĩa là theo mặc định, các giá trị không hợp lệ sẽ không được hiển thị. Điều này cũng có nghĩa là trường này sẽ không được kết xuất lại, vì isDirty_ sẽ không được đặt.

Nếu muốn hiển thị các giá trị không hợp lệ, bạn cần ghi đè doValueInvalid_. Trong hầu hết các trường hợp, bạn nên đặt thuộc tính displayValue_ thành giá trị không hợp lệ, đã đặt isDirty_ vào trueghi đè render_ để màn hình trên khối cập nhật dựa trên displayValue_ thay vì value_.

doValueInvalid_(newValue) {
  this.displayValue_ = newValue;
  this.isDirty_ = true;
  this.isValueValid_ = false;
}

Giá trị gồm nhiều phần

Khi trường của bạn chứa giá trị nhiều phần (ví dụ: danh sách, vectơ, đối tượng), bạn có thể muốn các phần được xử lý như các giá trị riêng lẻ.

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

Trong ví dụ trên, mỗi thuộc tính của newValue được xác thực riêng lẻ. Sau đó ở cuối hàm doClassValidation_, nếu có bất kỳ thuộc tính riêng lẻ nào không hợp lệ, giá trị này được lưu vào bộ nhớ đệm vào thuộc tính cacheValidatedValue_ trước khi trả về null (không hợp lệ). Lưu đối tượng vào bộ nhớ đệm bằng các lần xác thực riêng cho phép doValueInvalid_ xử lý chúng một cách riêng biệt, đơn giản bằng cách thực hiện một Hãy kiểm tra !this.cacheValidatedValue_.property thay vì xác thực lại từng thông báo thuộc tính riêng lẻ.

Mẫu này để xác thực các giá trị gồm nhiều phần cũng có thể được dùng trong lớp cục bộ trình xác thực hiện không có cách nào để thực thi mẫu này.

isDirty_

isDirty_ là một cờ được dùng trong setValue cũng như các phần khác của trường để cho biết liệu trường có cần kết xuất lại. Nếu giá trị hiển thị của trường này đã thay đổi, thì isDirty_ thường sẽ được đặt thành true.

Văn bản

→ Để biết thông tin về vị trí và sự khác biệt của văn bản của một trường từ giá trị của trường, xem Cấu trúc của .

Nếu văn bản trong trường khác với giá trị của trường, bạn nên ghi đè Hàm getText để cung cấp nội dung chính xác.

getText() {
  let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
  if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
    text += ' hat';
  }
  return text;
}

Tạo trình chỉnh sửa

Nếu bạn xác định hàm showEditor_, Blockly sẽ tự động lắng nghe nhấp chuột và gọi showEditor_ vào thời điểm thích hợp. Bạn có thể hiển thị bất kỳ HTML nào trong trình chỉnh sửa của bạn bằng cách gói nó vào một trong hai div đặc biệt, được gọi là DropDownDiv và WidgetDiv, nổi phía trên phần còn lại của giao diện người dùng của Blockly.

DropDownDiv dùng để cung cấp trình chỉnh sửa nằm bên trong một hộp được kết nối vào một trường. Nó tự động định vị ở gần trường trong khi vẫn ở nguyên vị trí trong giới hạn nhìn thấy được. Công cụ chọn góc và công cụ chọn màu là các ví dụ điển hình về DropDownDiv.

Hình ảnh công cụ chọn góc

WidgetDiv được dùng để cung cấp trình chỉnh sửa không hoạt động bên trong một hộp. Trường số sử dụng WidgetDiv để che trường bằng hộp nhập văn bản HTML. Trong khi thả xuống xử lý vị trí cho bạn, WidgetDiv thì không. Các phần tử cần phải là định vị theo cách thủ công. Hệ toạ độ được tính bằng toạ độ pixel so với phía trên cùng bên trái của cửa sổ. Trình chỉnh sửa nhập văn bản là một ví dụ hay về WidgetDiv.

Hình ảnh trình chỉnh sửa nhập văn bản

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

Mã mẫu 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);
}

Dọn dẹp

Cả DropDownDiv và xử lý WidgetDiv đều huỷ HTML của tiện ích nhưng bạn cần loại bỏ mọi trình nghe sự kiện mà bạn có theo cách thủ công áp dụng cho các phần tử đó.

widgetDispose_() {
  for (let i = this.editorListeners_.length, listener;
      listener = this.editorListeners_[i]; i--) {
    Blockly.browserEvents.unbind(listener);
    this.editorListeners_.pop();
  }
}

Hàm dispose được gọi trong ngữ cảnh null trên DropDownDiv. Bật WidgetDiv mà nó được gọi trong ngữ cảnh WidgetDiv. Trong cả hai trường hợp tốt nhất là bạn nên sử dụng liên kết khi truyền một hàm loại bỏ, như minh hoạ trong DropDownDiv ở trên và WidgetDiv ví dụ.

→ Để biết thông tin về cách loại bỏ (không dành riêng cho việc loại bỏ biên tập viên), hãy xem Loại bỏ.

Cập nhật màn hình on-block

Hàm render_ dùng để cập nhật màn hình trên khối của trường sao cho khớp giá trị nội bộ của nó.

Các ví dụ thường gặp bao gồm:

  • Thay đổi văn bản (trình đơn thả xuống)
  • Thay đổi màu sắc (màu sắc)

Mặc định

Hàm render_ mặc định đặt văn bản hiển thị thành kết quả của getDisplayText_ . Hàm getDisplayText_ trả về thuộc tính value_ của trường truyền đến một chuỗi, sau khi chuỗi được cắt ngắn để tuân theo văn bản tối đa thời lượng.

Nếu bạn đang sử dụng màn hình hiển thị trên khối mặc định và hành vi văn bản mặc định phù hợp với trường của bạn, nên bạn không cần ghi đè render_.

Nếu hành vi văn bản mặc định phù hợp với trường của bạn, nhưng trường lại bị chặn có các phần tử tĩnh bổ sung, bạn có thể gọi phương thức render_ mặc định nhưng bạn sẽ vẫn cần ghi đè hàm đó để cập nhật phiên bản kích thước.

Nếu hành vi văn bản mặc định không có tác dụng đối với trường của bạn hoặc màn hình on-block có các phần tử động bổ sung, bạn sẽ cần phải tuỳ chỉnh render_ .

Sơ đồ quy trình mô tả cách đưa ra quyết định xem có ghi đè hàm display_ hay không

Tuỳ chỉnh hiển thị

Nếu hành vi hiển thị mặc định không có tác dụng đối với trường của bạn, bạn sẽ cần xác định hành vi hiển thị tuỳ chỉnh. Điều này có thể liên quan đến bất cứ điều gì từ việc đặt chế độ cài đặt tuỳ chỉnh văn bản hiển thị, thay đổi các phần tử hình ảnh, đến cập nhật màu nền.

Tất cả các thay đổi thuộc tính DOM đều hợp pháp, hai điều duy nhất cần nhớ là:

  1. Việc tạo DOM phải được xử lý trong khởi chạy, vì hiệu quả hơn.
  2. Bạn phải luôn cập nhật size_ cho phù hợp với kích thước của màn hình trên khối.
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_();
}

Đang cập nhật kích thước

Việc cập nhật thuộc tính size_ của một trường là rất quan trọng vì việc này sẽ cung cấp thông tin mã kết xuất khối về cách định vị trường. Cách tốt nhất để tìm hiểu chính xác size_ phải là gì bằng cách thử nghiệm.

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

Màu khối khớp

Nếu bạn muốn các phần tử trong trường của mình khớp với màu của khối, chúng là được đính kèm, bạn nên ghi đè phương thức applyColour. Bạn sẽ muốn truy cập vào màu thông qua thuộc tính kiểu của khối.

applyColour() {
  const sourceBlock = this.sourceBlock_;
  if (sourceBlock.isShadow()) {
    this.arrow_.style.fill = sourceBlock.style.colourSecondary;
  } else {
    this.arrow_.style.fill = sourceBlock.style.colourPrimary;
  }
}

Đang cập nhật khả năng chỉnh sửa

Bạn có thể dùng hàm updateEditable để thay đổi cách trường của bạn xuất hiện tuỳ vào việc nội dung đó có thể chỉnh sửa được hay không. Hàm mặc định làm cho nó nền có/không có phản hồi khi di chuột (đường viền) nếu nền đó/không thể chỉnh sửa được. Màn hình trên khối không được thay đổi kích thước tuỳ thuộc vào khả năng chỉnh sửa của nó, nhưng tất cả các thay đổi khác đều được phép.

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

Chuyển đổi tuần tự

Chuyển đổi tuần tự có mục đích là lưu trạng thái của trường để có thể tải lại trường này vào không gian làm việc sau này.

Trạng thái không gian làm việc của bạn luôn bao gồm giá trị của trường, nhưng cũng có thể bao gồm trạng thái khác, chẳng hạn như trạng thái giao diện người dùng của trường. Ví dụ: nếu trường này là một bản đồ có thể thu phóng cho phép người dùng chọn quốc gia, bạn có thể cũng tuần tự hoá mức thu phóng.

Nếu trường của bạn có thể chuyển đổi tuần tự, bạn phải đặt thuộc tính SERIALIZABLE thành true

Blockly cung cấp 2 nhóm hook chuyển đổi tuần tự cho các trường. Một cặp móc hoạt động với hệ thống chuyển đổi tuần tự JSON mới, còn cặp còn lại hoạt động với hệ thống chuyển đổi tuần tự XML cũ.

saveStateloadState

saveStateloadState là các hook chuyển đổi tuần tự hoạt động với JSON mới hệ thống chuyển đổi tuần tự.

Trong một số trường hợp, bạn không cần cung cấp những thông tin này vì mặc định mới có hiệu quả. Nếu (1) trường của bạn là lớp con trực tiếp của cơ sở Lớp Blockly.Field, (2) giá trị của bạn là một JSON chuyển đổi tuần tự loại và (3) bạn chỉ cần chuyển đổi tuần tự giá trị, thì phương thức triển khai mặc định sẽ hoạt động tốt!

Nếu không, hàm saveState của bạn phải trả về một JSON có thể chuyển đổi tuần tự đối tượng/giá trị thể hiện trạng thái của trường. Và loadState của bạn phải chấp nhận cùng một đối tượng/giá trị có thể chuyển đổi tuần tự JSON và áp dụng đối tượng/giá trị đó cho trường này.

saveState() {
  return {
    'country': this.getValue(),  // Value state
    'zoom': this.getZoomLevel(), // UI state
  };
}

loadState(state) {
  this.setValue(state['country']);
  this.setZoomLevel(state['zoom']);
}

Dữ liệu sao lưu và chuyển đổi tuần tự đầy đủ

saveState cũng nhận được một tham số không bắt buộc là doFullSerialization. Đây là được sử dụng bởi các trường thường tham chiếu trạng thái được chuyển đổi tuần tự bởi trình chuyển đổi tuần tự (như mô hình dữ liệu sao lưu). Thông số này báo hiệu rằng trạng thái được tham chiếu sẽ không có sẵn khi khối được giải tuần tự, vì vậy sẽ tự thực hiện tất cả quá trình chuyển đổi tuần tự. Ví dụ: điều này đúng khi một khối riêng lẻ được chuyển đổi tuần tự hoặc khi một khối được sao chép và dán.

Có hai trường hợp sử dụng phổ biến cho vấn đề này:

  • Khi một khối riêng lẻ được tải vào một không gian làm việc nơi dữ liệu sao lưu mô hình không tồn tại, trường có đủ thông tin ở trạng thái riêng để để tạo một mô hình dữ liệu mới.
  • Khi một khối được sao chép và dán, trường này sẽ luôn tạo một bản sao lưu mới thay vì tham chiếu một mô hình dữ liệu hiện có.

Một trường sử dụng trường này là trường biến tích hợp sẵn. Thông thường, trình tự này sẽ chuyển đổi tuần tự mã của biến mà biến đó đang tham chiếu, nhưng nếu doFullSerialization là đúng nó sẽ chuyển đổi tuần tự tất cả trạng thái của mình.

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

Trường biến thực hiện việc này để đảm bảo rằng nếu được tải vào không gian làm việc khi biến không tồn tại, nó có thể tạo một biến mới để tham chiếu.

toXmlfromXml

toXmlfromXml là các hook chuyển đổi tuần tự hoạt động với XML cũ hệ thống chuyển đổi tuần tự. Chỉ sử dụng những nội dung hấp dẫn này nếu cần (ví dụ: bạn đang làm việc trên cơ sở mã cũ chưa được di chuyển), nếu không, hãy sử dụng saveStateloadState

Hàm toXml của bạn cần trả về một nút XML đại diện cho trạng thái của trường này. Hàm fromXml của bạn phải chấp nhận cùng một nút XML và áp dụng nó vào trường.

toXml(fieldElement) {
  fieldElement.textContent = this.getValue();
  fieldElement.setAttribute('zoom', this.getZoomLevel());
  return fieldElement;
}

fromXml(fieldElement) {
  this.setValue(fieldElement.textContent);
  this.setZoomLevel(fieldElement.getAttribute('zoom'));
}

Thuộc tính có thể chỉnh sửa và chuyển đổi tuần tự

Thuộc tính EDITABLE xác định xem trường này có phải có giao diện người dùng để cho biết rằng có thể tương tác với thiết bị đó. Thuộc tính này mặc định là true.

Thuộc tính SERIALIZABLE xác định xem trường này có được chuyển đổi tuần tự hay không. Nó mặc định là false. Nếu tài sản này là true, bạn có thể phải cung cấp các hàm chuyển đổi tuần tự và huỷ chuyển đổi tuần tự (xem Chuyển đổi tuần tự).

Tuỳ chỉnh con trỏ

Thuộc tính CURSOR xác định con trỏ mà người dùng nhìn thấy khi di chuột qua trường của bạn. Đó phải là một chuỗi con trỏ CSS hợp lệ. Chế độ mặc định là con trỏ do .blocklyDraggable xác định, đó là con trỏ bắt.