Las extensiones son funciones que se ejecutan en cada bloque de un tipo determinado mientras el bloque crear. A menudo, estos agregan una configuración o un comportamiento personalizados a un bloque.
Un mutador es un tipo especial de extensión que agrega serialización personalizada y a veces la IU, a un bloque.
Extensiones
Las extensiones son funciones que se ejecutan en cada bloque de un tipo determinado mientras el bloque crear. Pueden agregar una configuración personalizada (p. ej., configurar el cuadro de información del bloque). comportamiento personalizado (por ejemplo, agregar un objeto de escucha de eventos al bloque).
// This extension sets the block's tooltip to be a function which displays
// the parent block's tooltip (if it exists).
Blockly.Extensions.register(
'parent_tooltip_extension',
function() { // this refers to the block that the extension is being run on
var thisBlock = this;
this.setTooltip(function() {
var parent = thisBlock.getParent();
return (parent && parent.getInputsInline() && parent.tooltip) ||
Blockly.Msg.MATH_NUMBER_TOOLTIP;
});
});
Las extensiones se deben "registrar" para que puedan asociarse con una cadena
. Luego, puedes asignar esta clave de cadena a la propiedad extensions
de tu
JSON de tipo de bloque
definición para aplicar la
extensión al bloque.
{
//...,
"extensions": ["parent_tooltip_extension",]
}
También puede agregar varias extensiones a la vez. Ten en cuenta que el elemento extensions
La propiedad debe ser un array, incluso si solo aplicas una extensión.
{
//...,
"extensions": ["parent_tooltip_extension", "break_warning_extension"],
}
Mixes
Blockly también es un método útil para situaciones en las que quieras agregar algunas propiedades o funciones auxiliares a un bloque, pero no ejecutarlas de inmediato. Esta funciona permitiéndote registrar una mezcla que contenga todas las propiedades o los métodos adicionales. El objeto mixin se une a una función que aplica la combinación cada vez que se crea se crea el tipo de bloque determinado.
Blockly.Extensions.registerMixin('my_mixin', {
someProperty: 'a cool value',
someMethod: function() {
// Do something cool!
}
))`
Se puede hacer referencia a las claves de cadenas asociadas con combinaciones en JSON como a cualquier otro .
{
//...,
"extensions": ["my_mixin"],
}
Mutadores
Un mutador es un tipo especial de extensión que agrega serialización extra (extra
que se guarda y se carga) en un bloque. Por ejemplo, el sistema integrado
Los bloques controls_if
y list_create_with
necesitan serialización adicional para que
puede ahorrar cuántas entradas tiene.
Ten en cuenta que cambiar la forma del bloque no necesariamente significa que necesites
serialización adicional. Por ejemplo, el bloque math_number_property
cambia
forma, pero lo hace basándose en un campo desplegable, cuyo valor ya se
serializado. Por lo tanto, puede usar un campo
validador y no
necesitas un mutador.
Consulta el método serialización página de más información sobre cuándo necesitas un mutador y cuándo no.
Los mutadores también proporcionan una IU integrada para que los usuarios cambien las formas de los bloques si proporcionas algunos métodos opcionales.
Hooks de serialización
Los mutadores tienen dos pares de ganchos de serialización con los que trabajan. Un par de ganchos funciona con el nuevo sistema de serialización JSON, y el otro par trabaja con el el antiguo sistema de serialización XML. Debes proporcionar al menos uno de estos pares.
SaveExtraState y loadExtraState
saveExtraState
y loadExtraState
son hooks de serialización que funcionan con el
nuevo sistema de serialización JSON. saveExtraState
muestra un archivo JSON serializable
valor que representa el estado adicional del bloque, y loadExtraState
acepta ese mismo valor JSON serializable y lo aplica al bloque.
// These are the serialization hooks for the lists_create_with block.
saveExtraState: function() {
return {
'itemCount': this.itemCount_,
};
},
loadExtraState: function(state) {
this.itemCount_ = state['itemCount'];
// This is a helper function which adds or removes inputs from the block.
this.updateShape_();
},
El JSON resultante se verá de la siguiente manera:
{
"type": "lists_create_with",
"extraState": {
"itemCount": 3 // or whatever the count is
}
}
Sin estado
Si el bloque se encuentra en el estado predeterminado cuando se serializa, el
El método saveExtraState
puede mostrar null
para indicarlo. Si el
El método saveExtraState
muestra null
; por lo tanto, no se agrega ninguna propiedad extraState
.
el JSON. De esta manera, el tamaño del archivo para guardar se mantiene pequeño.
Datos de serialización y copia de seguridad completos
saveExtraState
también recibe un parámetro doFullSerialization
opcional. Esta
lo usan bloques que hacen referencia al estado serializado por una dirección
serializador (como modelos de datos de copia de seguridad). El parámetro indica que
el estado al que se hace referencia no estará disponible cuando se deserialice el bloque.
debe serializar todo el estado de copia de seguridad. Por ejemplo, este es
true cuando un bloque individual se serializa o cuando un bloque se copia y pega.
Dos casos de uso comunes para esto son los siguientes:
- Cuando se carga un bloque individual en un espacio de trabajo en el que los datos de copia de seguridad modelo no existe, tiene suficiente información en su propio estado para para crear un modelo de datos nuevo.
- Cuando se copia y pega un bloque, siempre se crea una copia de seguridad nueva en lugar de hacer referencia a uno existente.
Algunos de los bloques que usan esto son los
@blockly/block-shareable-procedures. Normalmente
serializan una referencia a un modelo de datos de copia de seguridad, que almacena su estado.
Pero si el parámetro doFullSerialization
es verdadero, entonces serializan
su estado. Los bloques de procedimiento que se pueden compartir usan esto para asegurarse de que cuando
se copia y pega, crea un nuevo modelo de datos de copia de seguridad, en lugar de hacer referencia a un
para el modelo existente.
mutationToDom y domToMutation
mutationToDom
y domToMutation
son hooks de serialización que funcionan con el
el antiguo sistema de serialización XML. Utiliza estos ganchos solo si debes hacerlo (p.ej.,
trabajando con una base de código antigua que todavía no se migró), de lo contrario, usa
saveExtraState
y loadExtraState
.
mutationToDom
muestra un nodo XML que representa el estado adicional del objeto
bloque, y domToMutation
acepta ese mismo nodo XML y aplica el estado a
el bloque.
// These are the old XML serialization hooks for the lists_create_with block.
mutationToDom: function() {
// You *must* create a <mutation></mutation> element.
// This element can have children.
var container = Blockly.utils.xml.createElement('mutation');
container.setAttribute('items', this.itemCount_);
return container;
},
domToMutation: function(xmlElement) {
this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10);
// This is a helper function which adds or removes inputs from the block.
this.updateShape_();
},
El XML resultante se verá de la siguiente manera:
<block type="lists_create_with">
<mutation items="3"></mutation>
</block>
Si tu función mutationToDom
muestra un valor nulo, no se aplicará ningún elemento adicional
agregado al XML.
Hooks de IU
Si proporcionas ciertas funciones como parte de tu mutador, Blockly agregará “mutador” predeterminado IU a tu bloque.
No necesitas usar esta IU si quieres agregar serialización adicional. Podrías usar una IU personalizada, como blocks-plus-minus complemento proporciona o puedes no usar ninguna IU.
componer y desglosar
La IU predeterminada se basa en las funciones compose
y decompose
.
decompose
"estalla" el bloque en subbloques más pequeños que se pueden mover
alrededor, se agregan y se borran. Esta función debería mostrar un "bloque superior" que es
es el bloque principal del lugar de trabajo del mutador al que se conectan los subbloques.
Luego, compose
interpreta la configuración de los subbloques y los usa para
modificar el bloque principal. Esta función debe aceptar el "bloque superior" que era
que muestra decompose
como parámetro.
Ten en cuenta que estas funciones se “mezclan” al bloque que está “mutando” así que this
para referirse a ese bloque.
// These are the decompose and compose functions for the lists_create_with block.
decompose: function(workspace) {
// This is a special sub-block that only gets created in the mutator UI.
// It acts as our "top block"
var topBlock = workspace.newBlock('lists_create_with_container');
topBlock.initSvg();
// Then we add one sub-block for each item in the list.
var connection = topBlock.getInput('STACK').connection;
for (var i = 0; i < this.itemCount_; i++) {
var itemBlock = workspace.newBlock('lists_create_with_item');
itemBlock.initSvg();
connection.connect(itemBlock.previousConnection);
connection = itemBlock.nextConnection;
}
// And finally we have to return the top-block.
return topBlock;
},
// The container block is the top-block returned by decompose.
compose: function(topBlock) {
// First we get the first sub-block (which represents an input on our main block).
var itemBlock = topBlock.getInputTargetBlock('STACK');
// Then we collect up all of the connections of on our main block that are
// referenced by our sub-blocks.
// This relates to the saveConnections hook (explained below).
var connections = [];
while (itemBlock && !itemBlock.isInsertionMarker()) { // Ignore insertion markers!
connections.push(itemBlock.valueConnection_);
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
// Then we disconnect any children where the sub-block associated with that
// child has been deleted/removed from the stack.
for (var i = 0; i < this.itemCount_; i++) {
var connection = this.getInput('ADD' + i).connection.targetConnection;
if (connection && connections.indexOf(connection) == -1) {
connection.disconnect();
}
}
// Then we update the shape of our block (removing or adding iputs as necessary).
// `this` refers to the main block.
this.itemCount_ = connections.length;
this.updateShape_();
// And finally we reconnect any child blocks.
for (var i = 0; i < this.itemCount_; i++) {
connections[i].reconnect(this, 'ADD' + i);
}
},
saveConnections
También puedes definir una función saveConnections
que se ejecute con
la IU predeterminada. Esta función te da la oportunidad de asociar los elementos secundarios de tu
el bloque principal (que existe en el espacio de trabajo principal) con los subbloques que existen en
en el lugar de trabajo del mutador. Luego, puedes usar estos datos para asegurarte de que tu compose
vuelve a conectar correctamente los elementos secundarios de tu bloque principal cuando
subbloques están reorganizados.
saveConnections
debe aceptar el "bloque superior" devuelto por tu decompose
la función como parámetro. Si la función saveConnections
está definida, Blockly
lo llamará antes de llamar a compose
.
saveConnections: function(topBlock) {
// First we get the first sub-block (which represents an input on our main block).
var itemBlock = topBlock.getInputTargetBlock('STACK');
// Then we go through and assign references to connections on our main block
// (input.connection.targetConnection) to properties on our sub blocks
// (itemBlock.valueConnection_).
var i = 0;
while (itemBlock) {
// `this` refers to the main block (which is being "mutated").
var input = this.getInput('ADD' + i);
// This is the important line of this function!
itemBlock.valueConnection_ = input && input.connection.targetConnection;
i++;
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
},
Registrándose
Los mutadores son solo un tipo especial de extensión, así que también deben se registran antes de que puedas usarlos en el archivo JSON definición.
// Function signature.
Blockly.Extensions.registerMutator(name, mixinObj, opt_helperFn, opt_blockList);
// Example call.
Blockly.Extensions.registerMutator(
'controls_if_mutator',
{ /* mutator methods */ },
undefined,
['controls_if_elseif', 'controls_if_else']);
name
: Es una cadena para asociar con el mutador de modo que puedas usarla en JSON.mixinObj
: Un objeto que contiene los diversos métodos de mutación. P.ej.,saveExtraState
yloadExtraState
.opt_helperFn
: Es una función auxiliar opcional que realizará lo siguiente: ejecutar en el bloque después de que se mezcle la mezcla.opt_blockList
: Es un array opcional de tipos de bloques (como cadenas) que se agregado al menú flotante en la IU predeterminada del mutador, si los métodos de la IU también definido.
Ten en cuenta que, a diferencia de las extensiones, cada tipo de bloque solo puede tener un mutador.
{
//...
"mutator": "controls_if_mutator"
}
Función auxiliar
Junto con la combinación, un mutador puede registrar una función auxiliar. Esta función es ejecutar en cada bloque del tipo dado una vez creado, y el mixinObj se agregado. Se puede usar para agregar activadores o efectos adicionales a una mutación.
Por ejemplo, puedes agregar un ayudante a tu bloque tipo lista que establezca la cantidad inicial de elementos:
var helper = function() {
this.itemCount_ = 5;
this.updateShape();
}