Trước khi tạo một loại trường mới, hãy cân nhắc xem một trong những phương thức khác để tuỳ chỉnh trường có phù hợp với nhu cầu của bạn hay không. Nếu ứng dụng của bạn cần lưu trữ một loại giá trị mới hoặc bạn muốn tạo một giao diện người dùng mới cho một loại giá trị hiện có, thì có thể bạn cần tạo một loại trường mới.
Để tạo một trường mới, hãy làm như sau:
- Triển khai hàm khởi tạo.
- Đăng ký khoá JSON và triển khai
fromJson
. - Xử lý quá trình khởi chạy giao diện người dùng trên khối và trình nghe sự kiện.
- Xử lý việc loại bỏ trình nghe sự kiện (việc loại bỏ giao diện người dùng sẽ được xử lý cho bạn).
- Triển khai tính năng xử lý giá trị.
- Thêm một bản trình bày bằng văn bản về giá trị của trường để hỗ trợ tiếp cận.
- Thêm các chức năng bổ sung, chẳng hạn như:
- Đị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à nắm rõ nội dung trong phần Cấu trúc của một trường.
Để xem ví dụ về trường tuỳ chỉnh, hãy xem bản minh hoạ Trường tuỳ chỉnh.
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 trình xác thực cục bộ. Hàm dựng của trường tuỳ chỉnh được gọi trong quá trình khởi tạo khối nguồn, bất kể khối nguồn được xác định bằng JSON hay JavaScript. Vì vậy, trường tuỳ 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ý phương thức
Hàm khởi tạo trường thường nhận một giá trị và một trình xác thực cục bộ. Giá trị này là không bắt buộc và nếu bạn không truyền giá trị (hoặc bạn truyền một giá trị không vượt qua quá trình xác thực lớp) thì giá trị mặc định của siêu lớp sẽ được sử dụng. Đối với lớp Field
mặc định, giá trị đó là null
. Nếu bạn không muốn giá trị mặc định đó, hãy nhớ truyền một giá trị phù hợp. Tham số trình xác thực chỉ xuất hiện cho 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 tài liệu Trình xác thực.
Cấu trúc
Logic bên trong hàm khởi tạo của bạn phải tuân theo quy trình sau:
- Gọi hàm khởi tạo siêu kế thừa (tất cả các trường tuỳ chỉnh phải kế thừa từ
Blockly.Field
hoặc một trong các lớp con của nó) để khởi tạo đúng giá trị và đặt trình xác thực cục bộ cho trường của bạn. - Nếu trường của bạn có thể được chuyển đổi 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 có thể chuyển đổi tuần tự và các trường có thể chỉnh sửa theo mặc định, vì vậy, bạn nên đặt thuộc tính này thành true, trừ phi bạn biết rằng thuộc tính này không được chuyển đổi tuần tự.
- Không bắt buộc: Áp dụng chế độ tuỳ chỉnh bổ sung (ví dụ: Trường nhãn cho phép truyền một lớp css, sau đó lớp này sẽ được áp dụng cho văn bản).
JSON và quy trình đăng ký
Trong định nghĩa khối JSON, các trường được mô tả bằng một chuỗi (ví dụ: field_number
, field_textinput
). Blockly duy trì một 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 vào bản đồ này, truyền vào lớp trường dưới dạng đối số thứ hai:
Blockly.fieldRegistry.register('field_generic', GenericField);
Bạn cũng cần xác định hàm fromJson
. Trước tiên, quá trình triển khai của bạn phải huỷ tham chiếu mọi tham chiếu đến mã thông báo bản địa hoá bằng cách sử dụng replaceMessageReferences, sau đó 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
Khi được tạo, trường của bạn về cơ bản chỉ chứa một giá trị. Khởi tạo là nơi DOM được tạo, mô hình được tạo (nếu trường có một mô hình) và các sự kiện được liên kết.
Hiển thị trên khối
Trong quá trình khởi tạo, bạn chịu trách nhiệm tạo mọi thứ bạn sẽ cần cho việc hiển thị trên khối của trường.
Mặc định, nền và văn bản
Hàm initView
mặc định tạo một phần tử rect
có màu sáng và một phần tử text
. Nếu bạn muốn trường của mình có cả hai, cộng với một số tính năng bổ sung, hãy gọi hàm initView
của lớp mẹ trước khi thêm phần còn lại của các phần tử DOM. Nếu muốn trường của mình có một trong hai phần tử này, nhưng không phải cả hai, bạn có thể sử 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à một trường văn bản chung (ví dụ: Text
Input), thì quá trình tạo DOM sẽ được xử lý cho bạn. Nếu không, bạn sẽ cần phải ghi đè hàm initView
để tạo các phần tử DOM mà bạn sẽ cần trong quá trình kết xuất trường sau này.
Ví dụ: một trường thả xuống có thể chứa cả hình ảnh và văn bản. Trong initView
, nó sẽ tạo một phần tử hình ảnh và một phần tử văn bản. Sau đó, trong render_
, nó sẽ hiện phần tử đang hoạt động và ẩn phần tử còn lại, dựa trên loại của lựa chọn đã chọn.
Bạn có thể tạo các phần tử DOM bằng phương thức Blockly.utils.dom.createSvgElement
hoặc bằng các phương thức tạo DOM truyền thống.
Các yêu cầu đối với chế độ 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. Nhóm trường được tạo tự động. - Tất cả các phần tử DOM phải nằm trong kích thước đã báo cáo của trường.
Hãy xem phần Kết xuất để biết thêm thông tin về cách tuỳ chỉnh và cập nhật màn hình hiển thị trên khối.
Thêm ký hiệu văn bản
Nếu 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ư biểu tượng độ của trường Góc), bạn có thể nối trực tiếp phần tử biểu tượng (thường có trong <tspan>
) vào 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 mousedown (được dùng để hiện trình chỉnh sửa).
Nếu muốn theo dõi các loại sự kiện khác (ví dụ: nếu muốn xử lý thao tác 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 hàm Blockly.utils.browserEvents.conditionalBind
. Phương thức liên kết sự kiện này sẽ lọc ra các thao tác chạm phụ trong quá trình kéo. Nếu muốn trình xử lý chạy ngay cả khi đang kéo, bạn có thể sử dụng hàm Blockly.browserEvents.bind
.
Thải bỏ
Nếu bạn đã đăng ký bất kỳ trình nghe sự kiện tuỳ chỉnh nào bên trong hàm bindEvents_
của trường, thì bạn sẽ cần huỷ đăng ký các trình nghe đó bên trong hàm dispose
.
Nếu bạn đã khởi chạy chế độ xem của trường một cách chính xác (bằng cách thêm tất cả các phần tử DOM vào fieldGroup_
), thì DOM của trường sẽ tự động bị loại bỏ.
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 phần Kết cấu của một trường.
Thứ tự 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ụ: các trường số chỉ được chấp nhận số, các trường màu chỉ được chấp nhận màu, v.v. Điều này được đảm bảo thông qua trình xác thực lớp và cục bộ. Trình xác thực lớp tuân theo các quy tắc tương tự như trình xác thực cục bộ, ngoại trừ việc trình xác thực này cũng được chạy trong hàm khởi tạo và do đó, trình xác thực này không được tham chiếu đến khối nguồn.
Để triển khai trình xác thực lớp của trường, hãy ghi đè hàm 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 đến một trường có setValue
là 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ànhnewValue
. - Đặt thuộc tính
isDirty_
thànhtrue
.
Nếu chỉ cần lưu trữ giá trị và không muốn thực hiện bất kỳ thao tác xử lý tuỳ chỉnh nào, bạn không cần ghi đè doValueUpdate_
.
Nếu không, nếu bạn muốn thực hiện các thao tác như:
- Bộ nhớ tuỳ chỉnh
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 truyền đến 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_
không làm gì cả. Điều này có nghĩa là theo mặc định, các giá trị không hợp lệ sẽ không xuất hiện. Điều này cũng có nghĩa là trường sẽ không được kết xuất lại vì thuộc tính isDirty_
sẽ không được đặt.
Nếu muốn hiển thị các giá trị không hợp lệ, bạn nê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_
thành true
và ghi đè render_ cho màn hình hiển thị 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ị có nhiều phần
Khi trường của bạn chứa một giá trị gồm 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
đều được xác thực riêng lẻ. Sau đó, ở cuối hàm doClassValidation_
, nếu có thuộc tính riêng lẻ nào không hợp lệ, giá trị sẽ được lưu vào bộ nhớ đệm cho thuộc tính cacheValidatedValue_
trước khi trả về null
(không hợp lệ). Việc lưu vào bộ nhớ đệm đối tượng bằng các thuộc tính được xác thực riêng lẻ cho phép hàm doValueInvalid_
xử lý các thuộc tính này riêng biệt, chỉ bằng cách thực hiện một thao tác kiểm tra !this.cacheValidatedValue_.property
, thay vì xác thực lại từng thuộc tính riêng lẻ.
Bạn cũng có thể sử dụng mẫu này để xác thực các giá trị gồm nhiều phần trong trình xác thực cục bộ nhưng hiện tại, không có cách nào để thực thi mẫu này.
isDirty_
isDirty_
là một cờ được dùng trong hàm setValue
, cũng như các phần khác của trường, để cho biết liệu trường có cần được kết xuất lại hay không. Nếu giá trị hiển thị của trường đã thay đổi, isDirty_
thường phải được đặt thành true
.
Văn bản
→ Để biết thông tin về vị trí sử dụng văn bản của một trường và điểm khác biệt giữa văn bản đó với giá trị của trường, hãy xem phần Kết cấu của một trường.
Nếu văn bản của trường khác với giá trị của trường, bạn nên ghi đè hàm getText
để cung cấp văn bản 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 người chỉnh sửa
Nếu bạn xác định hàm showEditor_
, Blockly sẽ tự động lắng nghe các lượt nhấp 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 bằng cách bao bọc HTML đó bằng một trong hai div đặc biệt, được gọi là DropDownDiv và WidgetDiv. Các div này sẽ nổi phía trên phần còn lại của giao diện người dùng Blockly.
DropDownDiv so với WidgetDiv
DropDownDiv
được dùng để cung cấp các trình chỉnh sửa nằm trong một hộp được kết nối với một trường. Nút này sẽ tự động đặt ở gần trường trong khi vẫn nằm trong phạm vi hiển thị. Công cụ chọn góc và công cụ chọn màu là những ví dụ điển hình về DropDownDiv
.
WidgetDiv
được dùng để cung cấp các trình chỉnh sửa không nằm trong một hộp. Các trường số sử dụng WidgetDiv để bao phủ trường bằng một hộp nhập văn bản HTML. Mặc dù DropDownDiv xử lý việc định vị cho bạn, nhưng WidgetDiv thì không. Bạn sẽ cần phải đặt vị trí các phần tử theo cách thủ công. Hệ toạ độ là toạ độ pixel tương ứng với phía trên cùng bên trái của cửa sổ. Trình chỉnh sửa văn bản là một ví dụ điển hình về WidgetDiv
.
Mã mẫu DropDownDiv
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à WidgetDiv đều xử lý việc huỷ các phần tử HTML của tiện ích, nhưng bạn cần huỷ bỏ mọi trình nghe sự kiện mà bạn đã áp dụng cho các phần tử đó theo cách thủ công.
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
. Trên WidgetDiv
, phương thức này được gọi trong ngữ cảnh của WidgetDiv
. Trong cả hai trường hợp, tốt nhất là bạn nên sử dụng hàm bind khi truyền một hàm dispose, như minh hoạ trong các ví dụ DropDownDiv
và WidgetDiv
ở trên.
→ Để biết thông tin về việc xử lý không dành riêng cho việc xử lý trình chỉnh sửa, hãy xem phần Xử lý.
Cập nhật màn hình hiển thị trên khối
Hàm render_
được dùng để cập nhật màn hình hiển thị trên khối của trường cho phù hợp với giá trị nội bộ của trường.
Sau đây là một số ví dụ phổ biến:
- Thay đổi văn bản (trình đơn thả xuống)
- Thay đổi màu sắc (màu)
Mặc định
Hàm render_
mặc định đặt văn bản hiển thị thành kết quả của hàm getDisplayText_
. Hàm getDisplayText_
trả về thuộc tính value_
của trường được truyền thành một chuỗi, sau khi thuộc tính đó bị cắt bớt để tuân thủ độ dài tối đa của văn bản.
Nếu đang sử dụng chế độ hiển thị mặc định trên khối và hành vi văn bản mặc định phù hợp với trường của bạn, thì 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 màn hình hiển thị trên khối của trường có thêm các phần tử tĩnh, bạn có thể gọi hàm render_
mặc định, nhưng bạn vẫn cần ghi đè hàm này để cập nhật kích thước của trường.
Nếu hành vi văn bản mặc định không hoạt động cho trường của bạn hoặc màn hình hiển thị trên khối của trường có thêm các phần tử động, bạn sẽ cần tuỳ chỉnh hàm render_
.
Tuỳ chỉnh hoạt động hiển thị
Nếu hành vi kết xuất mặc định không phù hợp với trường của bạn, thì bạn cần xác định hành vi kết xuất tuỳ chỉnh. Bạn có thể làm mọi thứ, từ việc đặt văn bản hiển thị tuỳ chỉnh, thay đổi các phần tử hình ảnh cho đến cập nhật màu nền.
Mọi thay đổi về thuộc tính DOM đều hợp lệ, bạn chỉ cần nhớ 2 điều sau:
- Bạn nên xử lý việc tạo DOM trong quá trình khởi chạy, vì việc này hiệu quả hơn.
- Bạn phải luôn cập nhật thuộc tính
size_
để khớp với kích thước của quảng cáo hiển thị 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ì thuộc tính này cho biết mã kết xuất khối cách định vị trường. Cách tốt nhất để xác định chính xác size_
đó là 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;
}
Ghép các khối màu
Nếu muốn các phần tử trong trường của bạn khớp với màu của khối mà chúng đượ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ỳ thuộc vào việc trường đó có thể chỉnh sửa hay không. Hàm mặc định giúp đảm bảo nền có/không có phản hồi di chuột (đường viền) nếu có/không chỉnh sửa được.
Màn hình hiển thị 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, 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ự
Tuần tự hoá là quá trình lưu trạng thái của trường để có thể tải lại vào không gian làm việc sau này.
Trạng thái của không gian làm việc 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 của giao diện người dùng của trường. Ví dụ: nếu trường của bạn là một bản đồ có thể thu phóng cho phép người dùng chọn quốc gia, thì bạn cũng có thể chuyển đổi cấp độ thu phóng thành chuỗi.
Nếu trường của bạn có thể được chuyển đổi tuần tự, bạn phải đặt thuộc tính SERIALIZABLE
thành true
.
Blockly cung cấp hai nhóm hook chuyển đổi tuần tự cho các trường. Một cặp hook hoạt động với hệ thống chuyển đổi tuần tự JSON mới và cặp còn lại hoạt động với hệ thống chuyển đổi tuần tự XML cũ.
saveState
và loadState
saveState
và loadState
là các hook tuần tự hoá hoạt động với hệ thống tuần tự hoá JSON mới.
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ì các chế độ triển khai mặc định sẽ hoạt động. Nếu (1) trường của bạn là một lớp con trực tiếp của lớp cơ sở Blockly.Field
, (2) giá trị của bạn là một loại có thể chuyển đổi tuần tự JSON và (3) bạn chỉ cần chuyển đổi tuần tự giá trị, thì quá trình triển khai mặc định sẽ hoạt động bình thường!
Nếu không, hàm saveState
của bạn phải trả về một đối tượng/giá trị có thể chuyển đổi tuần tự JSON, đại diện cho trạng thái của trường. Và hàm 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ự thành JSON và áp dụng đối tượng/giá trị đó cho trường.
saveState() {
return {
'country': this.getValue(), // Value state
'zoom': this.getZoomLevel(), // UI state
};
}
loadState(state) {
this.setValue(state['country']);
this.setZoomLevel(state['zoom']);
}
Toàn bộ quá trình chuyển đổi tuần tự và dữ liệu sao lưu
saveState
cũng nhận được một tham số không bắt buộc là doFullSerialization
. Trường này được dùng bởi các trường thường tham chiếu đến trạng thái được chuyển đổi tuần tự bằng một trình chuyển đổi tuần tự khác (chẳng hạn như các mô hình dữ liệu sao lưu). Tham 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 chuyển đổi tuần tự, vì vậy, trường nà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.
Sau đây là 2 trường hợp sử dụng phổ biến cho việc này:
- Khi một khối riêng lẻ được tải vào một không gian làm việc mà mô hình dữ liệu hỗ trợ không tồn tại, trường này có đủ thông tin trong 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 luôn tạo một mô hình dữ liệu hỗ trợ mới thay vì tham chiếu đến một mô hình hiện có.
Một trường sử dụng biến này là trường biến được tạo sẵn. Thông thường, nó sẽ chuyển đổi mã nhận dạng của biến mà nó đang tham chiếu thành dữ liệu nối tiếp, nhưng nếu doFullSerialization
có giá trị true, thì nó sẽ chuyển đổi tất cả trạng thái của biến đó thành dữ liệu nối tiếp.
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 một không gian làm việc mà biến của nó không tồn tại, thì trường biến có thể tạo một biến mới để tham chiếu.
toXml
và fromXml
toXml
và fromXml
là các hook tuần tự hoá hoạt động với hệ thống tuần tự hoá XML cũ. Bạn chỉ nên sử dụng các hook này nếu bắt buộc (ví dụ: bạn đang làm việc trên một cơ sở mã cũ chưa được di chuyển), nếu không, hãy sử dụng saveState
và loadState
.
Hàm toXml
của bạn phải trả về một nút XML đại diện cho trạng thái của trường. 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út đó cho 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 có nên có giao diện người dùng để cho biết rằng trường đó có thể tương tác hay không. Giá trị mặc định là true
.
Thuộc tính SERIALIZABLE
xác định xem trường có được chuyển đổi tuần tự hay không. Giá trị mặc định là false
. Nếu thuộc tính này là true
, bạn có thể cần cung cấp các hàm chuyển đổi tuần tự và giải tuần tự (xem Chuyển đổi tuần tự).
Tuỳ chỉnh bằng CSS
Bạn có thể tuỳ chỉnh trường bằng CSS. Trong phương thức initView
, hãy thêm một lớp tuỳ chỉnh vào fieldGroup_
của trường, sau đó tham chiếu lớp này trong CSS.
Ví dụ: để sử dụng một con trỏ khác:
initView() {
...
// Add a custom CSS class.
if (this.fieldGroup_) {
Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField');
}
}
.myCustomField {
cursor: cell;
}
Tuỳ chỉnh con trỏ
Theo mặc định, các lớp mở rộng FieldInput
sẽ sử dụng con trỏ text
khi người dùng di chuột qua trường, các trường đang được kéo sẽ sử dụng con trỏ grabbing
và tất cả các trường khác sẽ sử dụng con trỏ default
. Nếu bạn muốn sử dụng một con trỏ khác, hãy đặt con trỏ đó bằng CSS.