커스텀 필드 업그레이드

2019년 7월 (버전 2.20190722)에는 좀 더 코드화된 필드 API가 추가되었습니다. 가능한 한 이전 버전과 호환되도록 되어 있습니다. 즉, 2019년 7월 이전에 맞춤 필드를 만들었다면 계속 작동할 가능성이 높습니다. 커스텀 필드를 업그레이드해야 하는지 결정하기 전에 위험 영역 섹션을 읽고 필드를 철저하게 테스트해야 합니다.

2019년 7월 이전에는 필드 간 표준화가 부족했기 때문에 개발자가 적용해야 할 모든 변경사항을 다루기가 까다롭습니다. 이 문서에서는 가능한 모든 변경사항을 다루려고 하지만, 관심이 있는 내용이 이 문서에서 다루지 않는 경우 업그레이드 지원 받기 섹션을 참고하세요.

위험 지역

위험 영역은 API가 변경된 것으로 알려진 장소로, 필드가 손상될 수 있습니다.

Blockly.Field.register

필드가 더 이상 Blockly.Field.register();을 통해 등록되지 않습니다. 이제 등록을 처리하는 fieldRegistry 네임스페이스가 있습니다.

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

위의 내용이 아래와 같이 변합니다.

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

setText

setText 함수는 더 이상 Blockly 코어에서 호출하지 않으므로 setText 함수에 로직이 포함된 경우 (setText 함수가 정확히 실행하는 작업에 따라) 값 처리 함수 모음, getText 함수, 렌더링 함수로 이동해야 합니다.

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

위의 내용이 아래와 같이 변합니다.

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

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

다음을 자동으로 처리합니다.

  • 새 값이 이전 값과 다른지 확인합니다.
  • 값 업데이트 중
  • 변경 이벤트를 실행하는 중입니다.
  • 필드를 다시 렌더링하는 중입니다.

다음을 처리해야 합니다.

권장 업그레이드는 필드 API가 변경되었지만 변경하지 않을 경우에도 필드가 계속 작동할 가능성이 높습니다.

직렬

EDITABLESERIALIZABLE 속성에 관한 자세한 내용은 수정 가능한 속성 및 직렬화 가능한 속성을 참고하세요.

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

아래 경고는 무시할 수 있지만 SERIALIZABLE 속성을 정의하여 해결할 수 있습니다.

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

위의 경고는 Blockly가 EDITABLE 속성이 true이므로 필드를 직렬화해야 한다고 생각하지만 SERIALIZABLE 속성을 정의할 때까지는 확신할 수 없다는 의미입니다. 이 단계를 그대로 두면 모든 것이 제대로 작동하고 필드가 직렬화되지만 콘솔 경고가 표시됩니다.

size_.width

this.size_.width = 0;

위의 내용이 아래와 같이 변합니다.

this.isDirty_ = true;

아래 경고는 무시할 수 있지만 size_.width 속성 대신 isDirty_ 속성을 설정하여 해결할 수 있습니다.

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

위의 경고는 Blockly에서 필드를 다시 렌더링하는 이전 메서드를 사용하고 있음을 감지했으며, 새 메서드를 사용하길 원한다는 의미입니다.

isDirty_ 속성에 관한 자세한 내용은 isDirty_를 참고하세요.

init

서브클래스에서 중복 코드를 줄이기 위해 init 함수를 템플릿 함수로 만들었습니다.

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

위의 내용이 아래와 같이 변합니다.

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

즉, 이제 blockly에서 다음을 자동으로 처리합니다.

  • 필드가 이미 초기화되었는지 확인합니다.
  • fieldGroup_를 만드는 중입니다.
  • 필드 렌더링
  • 결합 도움말 및 편집기 이벤트 표시

다음을 처리해야 합니다.

onMouseDown_

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

위의 내용이 아래와 같이 변합니다.

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

onMouseDown_ 함수보다 마우스 클릭을 처리하도록 showEditor_ 함수를 재정의하여 입력이 동작 시스템을 통과할 수 있도록 하는 것이 좋습니다.

편집기에 관한 자세한 내용은 편집기를 참고하세요.

setValue

setValue 함수는 이제 서브클래스에서 중복 코드를 줄이는 템플릿 함수입니다. setValue 함수에 로직이 포함되어 있으면 값 처리에 설명된 값 처리 경로에 맞게 리팩터링하는 것이 좋습니다.

text_

필드의 text_ 속성에 직접 액세스하거나 업데이트하지 않는 것이 좋습니다. 대신 getText 함수를 사용하여 사용자가 읽을 수 있는 필드 텍스트에 액세스하고 setValue 함수를 사용하여 필드의 저장된 값을 업데이트하세요.

필드의 값과 텍스트를 비교한 자세한 내용은 필드 분석을 참조하세요.

업그레이드 지원 받기

제공 내용

도움을 요청할 때는 다음과 같이 구체적인 질문을 하는 것이 가장 좋습니다.

권장하지 않음: '이 입력란에 어떤 문제가 있나요?'

'이 필드 업그레이드 관련 도움 받기'도 권장하지 않습니다.

권장: '입력란 텍스트가 올바르게 업데이트되지 않습니다.'

또한 귀하를 지원하는 사람들에게 리소스를 제공하는 것도 필요합니다. 이러한 파일은 다른 사용자가 쉽게 사용할 수 있어야 합니다.

다음은 권장하지 않습니다.

  • 코드 이미지
  • 코드가 불완전합니다.

권장:

  • 텍스트 형식으로 입력란 코드를 작성합니다.
  • 비정상적인 필드 동작을 보여주는 GIF 이미지
  • 잘못된 필드 동작을 재현하기 위한 단계
  • 업그레이드할 Blockly의 버전입니다.

게시 위치

블록 개발자 포럼에 업그레이드 관련 질문을 게시하세요.

이 문제가 블록리 코어의 문제라고 확신하는 경우 블록별 GitHub에 문제를 게시할 수도 있습니다. 문제를 게시하려면 요청된 모든 정보를 작성하세요.