Em julho de 2019 (versão 2.20190722), foi adicionada uma API de campos mais codificada. O objetivo é que ele seja o mais compatível possível com versões anteriores. Isso significa que, se você criou um campo personalizado antes de julho de 2019, ele provavelmente vai continuar funcionando. Antes de decidir se o campo personalizado precisa ser atualizado, leia a seção Áreas de risco e teste o campo completamente.
Como não havia padronização entre os campos antes de julho de 2019, é difícil abranger todas as mudanças que um desenvolvedor pode precisar fazer. Este documento tenta abordar todas as mudanças prováveis, mas se ele não abordar algo do seu interesse, leia a seção sobre receber assistência para upgrade.
Áreas de perigo
As áreas de risco são locais conhecidos em que a API mudou e seu campo pode ser interrompido.
Blockly.Field.register
Os campos não são mais registrados pelo Blockly.Field.register();
. Agora há um namespace fieldRegistry
que processa o registro.
Blockly.Field.register('my_field_name', myFieldClass);
O resultado é:
Blockly.fieldRegistry.register('my_field_name', myFieldClass);
setText
A função setText
não é mais chamada pelo núcleo do Blockly. Portanto, se a função setText
contiver lógica, ela precisará ser movida para o
conjunto de funções de processamento de valores, a função getText
e as funções de renderização
(dependendo do que exatamente a função setText
está fazendo).
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;
};
O resultado é:
CustomFields.UpgradeField.prototype.doClassValidation_ = function(newValue) {
if (typeof newValue != 'string') {
return null;
}
return newValue;
};
CustomFields.UpgradeField.prototype.getText = function() {
return 'prefix' + this.value_;
}
O Blockly processa automaticamente:
- Verificar se o novo valor é diferente do antigo.
- Atualizando o valor.
- Acionamento de eventos de mudança.
- Renderizando o campo novamente.
Você vai precisar lidar com:
- Validação de valor (
doClassValidation_
). - Texto do campo (
getText
). - Interface de campo
Upgrades recomendados
Os upgrades recomendados são locais em que a API de campo foi alterada, mas, se você optar por não fazer mudanças, seu campo provavelmente ainda vai funcionar.
SERIALIZABLE
Para mais informações sobre as propriedades EDITABLE
e SERIALIZABLE
, consulte
Propriedades editáveis e serializáveis.
CustomFields.UpgradeField.prototype.SERIALIZABLE = true;
O aviso abaixo pode ser ignorado, mas você pode resolver o problema definindo a propriedade SERIALIZABLE
:
Detected an editable field that was not serializable. Please define
SERIALIZABLE property as true on all editable custom fields. Proceeding
with serialization.
O aviso acima significa que o Blockly acredita que você quer que o
campo seja serializado (porque a propriedade EDITABLE
é verdadeira), mas
não pode ter certeza até que você defina a propriedade SERIALIZABLE
. Se você não fizer nada, tudo vai funcionar corretamente, e seu campo será serializado, mas você vai receber avisos no console.
size_.width
this.size_.width = 0;
O resultado é:
this.isDirty_ = true;
O aviso abaixo pode ser ignorado, mas você pode resolver o problema definindo a propriedade isDirty_
em vez de size_.width
:
Deprecated use of setting size_.width to 0 to rerender a field. Set
field.isDirty_ to true instead.
O aviso acima significa que o Blockly detectou que você está usando um método antigo para renderizar novamente um campo e gostaria que você usasse o novo método.
Para mais informações sobre a propriedade isDirty_
, consulte
isDirty_.
init
A função init
foi transformada em uma função de modelo para reduzir o código duplicado em subclasses.
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());
};
O resultado é:
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_);
};
Isso significa que o Blockly agora processa automaticamente:
- Verificar se o campo já foi inicializado.
- Como criar o
fieldGroup_
. - Renderização do campo.
- Tooltip de vinculação e eventos do editor de exibição.
Você vai precisar lidar com:
- Adicionar outros elementos DOM (
initView
). - Adição de outras vinculações de eventos (
bindEvents_
). - Descartar vinculações de eventos (
dispose
).
onMouseDown_
CustomFields.UpgradeField.prototype.onMouseDown_ = function(e) {
// ...
};
O resultado é:
CustomFields.UpgradeField.prototype.showEditor_ = function() {
// ...
}
Recomendamos que você substitua a função showEditor_
para processar cliques do mouse em vez da função onMouseDown_
, já que isso permite que a entrada passe pelo sistema de gestos.
Para mais informações sobre editores, consulte Editores.
setValue
A função setValue
agora é uma função de modelo para reduzir o código duplicado em subclasses. Se a função setValue
tiver lógica,
refatore-a para se adequar aos caminhos de processamento de valores descritos em
Processamento de valores.
text_
Recomendamos que você nunca acesse ou atualize diretamente a propriedade text_
do seu
campo. Em vez disso, use a função
getText
para acessar o texto legível do usuário do seu campo e a função
setValue
para atualizar o valor armazenado do seu campo.
Para mais informações sobre o valor de um campo e o texto dele, consulte Anatomia de um campo.
Receber assistência de upgrade
O que fornecer
Ao pedir ajuda, é melhor fazer perguntas específicas:
Não recomendado: "O que há de errado com este campo?"
Também não é recomendável: "Me ajude a fazer upgrade deste campo".
Recomendado: "O texto do campo não está sendo atualizado corretamente".
Também é necessário fornecer recursos para as pessoas que estão ajudando você. Esses arquivos precisam ser fáceis de usar para outras pessoas.
Não recomendado:
- Imagens de código.
- Código incompleto.
Recomendado:
- Preencha o código do campo em um formato de texto.
- Imagens de GIFs de mau comportamento em campo.
- Etapas para reproduzir o comportamento incorreto do campo.
- A versão do Blockly de que você está fazendo upgrade.
Onde postar
Poste perguntas sobre a atualização no fórum de desenvolvedores do Blockly.
Se você tiver certeza de que o problema está no núcleo do Blockly, também poderá postar um problema no GitHub do Blockly. Se você decidir postar um problema, preencha todas as informações solicitadas.