blockly是什么
少啰嗦,先看东西

blockly能做什么:通过拖动块产生代码;生产的代码可以是JS,Python,PHP,Lua,Dart,以下亲测两种。
下图为生成的 Python 和 JS 代码

个人使用心得:
优势:强大的blockly,可以几乎可以生成任何公式,甚至非常复杂的公式或者规则;
缺点:对于程序员简单,对非程序员的使用者学习成本有点高,甚至要求有点程序基础,例如让一个HR去用这个东西开始可能抵触心理很大;
安装
npm install blockly
注意:如果安装失败,请删除node_modules后再重装
少啰嗦,先看demo
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Button } from 'antd';
import Blockly from 'blockly';
import * as Ch from 'blockly/msg/zh-hans';
// import * as Blockly_core from 'blockly/core'; zh-hans.js
import 'blockly/blocks';
import 'blockly/python';
import XmlBlockly from './blockly_xml';
export default () => {
const blockId = useRef('blocklyDiv');// 薪酬模块
useEffect(()=>{
Blockly.setLocale(Ch); // 支持中文
if(blockId.current && document.getElementById(blockId.current)){
const workspace = Blockly.inject('blocklyDiv',{toolbox: document.getElementById('toolbox')});
function myUpdateFunction(event) {
const code_js = Blockly.JavaScript.workspaceToCode(workspace);
console.log('code_js: ', code_js);
// const code = Blockly.Xml.workspaceToDom(workspace);
// const code_python = Blockly.Python.workspaceToCode(workspace);
// console.log('code_python: ', code_python);
const xml = Blockly.Xml.workspaceToDom(workspace);
const xml_text = Blockly.Xml.domToText(xml);
window.localStorage.setItem('xml_text',xml_text);
}
workspace.addChangeListener(myUpdateFunction);
const xml_text = window.localStorage.getItem('xml_text');
const xml = Blockly.Xml.textToDom(xml_text);
Blockly.Xml.domToWorkspace(xml, workspace);
}
},[blockId.current])
return (
<>
<div id={blockId.current} style={{height: '715px', width: '100%', overflow: 'auto'}}></div>
<XmlBlockly />
<div className={styles.drag} draggable>draggable</div>
</>
)
}
blockly_xml.js
import React from 'react';
function Xml_Blockly(){
return(
<xml id="toolbox" style={{display:'none'}}>
<category name="逻辑" colour="#5C81A6">
<block type="controls_if"></block>
<block type="logic_compare">
<field name="OP">EQ</field>
</block>
<block type="logic_operation">
<field name="OP">AND</field>
</block>
<block type="logic_negate"></block>
<block type="logic_boolean">
<field name="BOOL">TRUE</field>
</block>
<block type="logic_null"></block>
<block type="logic_ternary"></block>
</category>
<category name="循环" colour="#5CA65C">
<block type="controls_repeat_ext">
<value name="TIMES">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="controls_whileUntil">
<field name="MODE">WHILE</field>
</block>
<block type="controls_for">
<field name="VAR" id="cV8(8gw)4+2F=@{-oa%U" variabletype="">i</field>
<value name="FROM">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="TO">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
<value name="BY">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
<block type="controls_forEach">
<field name="VAR" id="49TAe6j@7~K]V3lvrC!i" variabletype="">j</field>
</block>
<block type="controls_flow_statements">
<field name="FLOW">BREAK</field>
</block>
</category>
<category name="数学运算" colour="#5C68A6">
<block type="math_round">
<field name="OP">ROUND</field>
<value name="NUM">
<shadow type="math_number">
<field name="NUM">3.1</field>
</shadow>
</value>
</block>
<block type="math_number">
<field name="NUM">0</field>
</block>
<block type="math_single">
<field name="OP">ROOT</field>
<value name="NUM">
<shadow type="math_number">
<field name="NUM">9</field>
</shadow>
</value>
</block>
<block type="math_trig">
<field name="OP">SIN</field>
<value name="NUM">
<shadow type="math_number">
<field name="NUM">45</field>
</shadow>
</value>
</block>
<block type="math_constant">
<field name="CONSTANT">PI</field>
</block>
<block type="math_number_property">
<mutation divisor_input="false"></mutation>
<field name="PROPERTY">EVEN</field>
<value name="NUMBER_TO_CHECK">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>
<block type="math_arithmetic">
<field name="OP">ADD</field>
<value name="A">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="B">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
<block type="math_on_list">
<mutation op="SUM"></mutation>
<field name="OP">SUM</field>
</block>
<block type="math_modulo">
<value name="DIVIDEND">
<shadow type="math_number">
<field name="NUM">64</field>
</shadow>
</value>
<value name="DIVISOR">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="math_constrain">
<value name="VALUE">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="LOW">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="HIGH">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>
<block type="math_random_int">
<value name="FROM">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="TO">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>
<block type="math_random_float"></block>
</category>
<category name="文本" colour="#5CA68D">
<block type="text_charAt">
<mutation at="true"></mutation>
<field name="WHERE">FROM_START</field>
<value name="VALUE">
<block type="variables_get">
<field name="VAR" id="B0!JU8*uGn](FPPot0b8" variabletype="">text</field>
</block>
</value>
</block>
<block type="text">
<field name="TEXT"></field>
</block>
<block type="text_append">
<field name="VAR" id="-*Z%h!C8]8?:CrB^l[Sb" variabletype="">item</field>
<value name="TEXT">
<shadow type="text">
<field name="TEXT"></field>
</shadow>
</value>
</block>
<block type="text_length">
<value name="VALUE">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_isEmpty">
<value name="VALUE">
<shadow type="text">
<field name="TEXT"></field>
</shadow>
</value>
</block>
<block type="text_indexOf">
<field name="END">FIRST</field>
<value name="VALUE">
<block type="variables_get">
<field name="VAR" id="B0!JU8*uGn](FPPot0b8" variabletype="">text</field>
</block>
</value>
<value name="FIND">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_join">
<mutation items="2"></mutation>
</block>
<block type="text_getSubstring">
<mutation at1="true" at2="true"></mutation>
<field name="WHERE1">FROM_START</field>
<field name="WHERE2">FROM_START</field>
<value name="STRING">
<block type="variables_get">
<field name="VAR" id="B0!JU8*uGn](FPPot0b8" variabletype="">text</field>
</block>
</value>
</block>
<block type="text_changeCase">
<field name="CASE">UPPERCASE</field>
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_trim">
<field name="MODE">BOTH</field>
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_print">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_prompt_ext">
<mutation type="TEXT"></mutation>
<field name="TYPE">TEXT</field>
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
</category>
<category name="数组" colour="#745CA6">
<block type="lists_indexOf">
<field name="END">FIRST</field>
<value name="VALUE">
<block type="variables_get">
<field name="VAR" id="Jk,w-5|uh#:o4}s(K7F*" variabletype="">list</field>
</block>
</value>
</block>
<block type="lists_create_with">
<mutation items="0"></mutation>
</block>
<block type="lists_repeat">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">5</field>
</shadow>
</value>
</block>
<block type="lists_length"></block>
<block type="lists_isEmpty"></block>
<block type="lists_create_with">
<mutation items="3"></mutation>
</block>
<block type="lists_getIndex">
<mutation statement="false" at="true"></mutation>
<field name="MODE">GET</field>
<field name="WHERE">FROM_START</field>
<value name="VALUE">
<block type="variables_get">
<field name="VAR" id="Jk,w-5|uh#:o4}s(K7F*" variabletype="">list</field>
</block>
</value>
</block>
<block type="lists_setIndex">
<mutation at="true"></mutation>
<field name="MODE">SET</field>
<field name="WHERE">FROM_START</field>
<value name="LIST">
<block type="variables_get">
<field name="VAR" id="Jk,w-5|uh#:o4}s(K7F*" variabletype="">list</field>
</block>
</value>
</block>
<block type="lists_getSublist">
<mutation at1="true" at2="true"></mutation>
<field name="WHERE1">FROM_START</field>
<field name="WHERE2">FROM_START</field>
<value name="LIST">
<block type="variables_get">
<field name="VAR" id="Jk,w-5|uh#:o4}s(K7F*" variabletype="">list</field>
</block>
</value>
</block>
<block type="lists_split">
<mutation mode="SPLIT"></mutation>
<field name="MODE">SPLIT</field>
<value name="DELIM">
<shadow type="text">
<field name="TEXT">,</field>
</shadow>
</value>
</block>
<block type="lists_sort">
<field name="TYPE">NUMERIC</field>
<field name="DIRECTION">1</field>
</block>
</category>
<category name="颜色" colour="#A6745C">
<block type="colour_picker">
<field name="COLOUR">#ff0000</field>
</block>
<block type="colour_random"></block>
<block type="colour_rgb">
<value name="RED">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="GREEN">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="BLUE">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>
<block type="colour_blend">
<value name="COLOUR1">
<shadow type="colour_picker">
<field name="COLOUR">#ff0000</field>
</shadow>
</value>
<value name="COLOUR2">
<shadow type="colour_picker">
<field name="COLOUR">#3333ff</field>
</shadow>
</value>
<value name="RATIO">
<shadow type="math_number">
<field name="NUM">0.5</field>
</shadow>
</value>
</block>
</category>
<category name="变量" colour="#A65C81" custom="VARIABLE"></category>
<category name="函数" colour="#9A5CA6" custom="PROCEDURE"></category>
</xml>)
}
export default Xml_Blockly;
使用(只针对react的使用,其他先不介绍)
import Blockly from 'blockly'; // 引用
render(
return(
<>
<div id={blockId.current} style={{height: '715px', width: '100%', overflow: 'auto'}}></div>
<xml id="toolbox" style={{display:'none'}}>
<category name="逻辑" colour="#5C81A6">
<block type="controls_if"></block>
<block type="logic_compare">
<field name="OP">EQ</field>
</block>
<block type="logic_operation">
<field name="OP">AND</field>
</block>
<block type="logic_negate"></block>
<block type="logic_boolean">
<field name="BOOL">TRUE</field>
</block>
<block type="logic_null"></block>
<block type="logic_ternary"></block>
</category>
<category name="循环" colour="#5CA65C">
<block type="controls_repeat_ext">
<value name="TIMES">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="controls_whileUntil">
<field name="MODE">WHILE</field>
</block>
<block type="controls_for">
<field name="VAR" id="cV8(8gw)4+2F=@{-oa%U" variabletype="">i</field>
<value name="FROM">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="TO">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
<value name="BY">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
<block type="controls_forEach">
<field name="VAR" id="49TAe6j@7~K]V3lvrC!i" variabletype="">j</field>
</block>
<block type="controls_flow_statements">
<field name="FLOW">BREAK</field>
</block>
</category>
<category name="数学运算" colour="#5C68A6">
<block type="math_round">
<field name="OP">ROUND</field>
<value name="NUM">
<shadow type="math_number">
<field name="NUM">3.1</field>
</shadow>
</value>
</block>
<block type="math_number">
<field name="NUM">0</field>
</block>
<block type="math_single">
<field name="OP">ROOT</field>
<value name="NUM">
<shadow type="math_number">
<field name="NUM">9</field>
</shadow>
</value>
</block>
<block type="math_trig">
<field name="OP">SIN</field>
<value name="NUM">
<shadow type="math_number">
<field name="NUM">45</field>
</shadow>
</value>
</block>
<block type="math_constant">
<field name="CONSTANT">PI</field>
</block>
<block type="math_number_property">
<mutation divisor_input="false"></mutation>
<field name="PROPERTY">EVEN</field>
<value name="NUMBER_TO_CHECK">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>
<block type="math_arithmetic">
<field name="OP">ADD</field>
<value name="A">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="B">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
<block type="math_on_list">
<mutation op="SUM"></mutation>
<field name="OP">SUM</field>
</block>
<block type="math_modulo">
<value name="DIVIDEND">
<shadow type="math_number">
<field name="NUM">64</field>
</shadow>
</value>
<value name="DIVISOR">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>
<block type="math_constrain">
<value name="VALUE">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="LOW">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="HIGH">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>
<block type="math_random_int">
<value name="FROM">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="TO">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>
<block type="math_random_float"></block>
</category>
<category name="文本" colour="#5CA68D">
<block type="text_charAt">
<mutation at="true"></mutation>
<field name="WHERE">FROM_START</field>
<value name="VALUE">
<block type="variables_get">
<field name="VAR" id="B0!JU8*uGn](FPPot0b8" variabletype="">text</field>
</block>
</value>
</block>
<block type="text">
<field name="TEXT"></field>
</block>
<block type="text_append">
<field name="VAR" id="-*Z%h!C8]8?:CrB^l[Sb" variabletype="">item</field>
<value name="TEXT">
<shadow type="text">
<field name="TEXT"></field>
</shadow>
</value>
</block>
<block type="text_length">
<value name="VALUE">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_isEmpty">
<value name="VALUE">
<shadow type="text">
<field name="TEXT"></field>
</shadow>
</value>
</block>
<block type="text_indexOf">
<field name="END">FIRST</field>
<value name="VALUE">
<block type="variables_get">
<field name="VAR" id="B0!JU8*uGn](FPPot0b8" variabletype="">text</field>
</block>
</value>
<value name="FIND">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_join">
<mutation items="2"></mutation>
</block>
<block type="text_getSubstring">
<mutation at1="true" at2="true"></mutation>
<field name="WHERE1">FROM_START</field>
<field name="WHERE2">FROM_START</field>
<value name="STRING">
<block type="variables_get">
<field name="VAR" id="B0!JU8*uGn](FPPot0b8" variabletype="">text</field>
</block>
</value>
</block>
<block type="text_changeCase">
<field name="CASE">UPPERCASE</field>
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_trim">
<field name="MODE">BOTH</field>
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_print">
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
<block type="text_prompt_ext">
<mutation type="TEXT"></mutation>
<field name="TYPE">TEXT</field>
<value name="TEXT">
<shadow type="text">
<field name="TEXT">abc</field>
</shadow>
</value>
</block>
</category>
<category name="数组" colour="#745CA6">
<block type="lists_indexOf">
<field name="END">FIRST</field>
<value name="VALUE">
<block type="variables_get">
<field name="VAR" id="Jk,w-5|uh#:o4}s(K7F*" variabletype="">list</field>
</block>
</value>
</block>
<block type="lists_create_with">
<mutation items="0"></mutation>
</block>
<block type="lists_repeat">
<value name="NUM">
<shadow type="math_number">
<field name="NUM">5</field>
</shadow>
</value>
</block>
<block type="lists_length"></block>
<block type="lists_isEmpty"></block>
<block type="lists_create_with">
<mutation items="3"></mutation>
</block>
<block type="lists_getIndex">
<mutation statement="false" at="true"></mutation>
<field name="MODE">GET</field>
<field name="WHERE">FROM_START</field>
<value name="VALUE">
<block type="variables_get">
<field name="VAR" id="Jk,w-5|uh#:o4}s(K7F*" variabletype="">list</field>
</block>
</value>
</block>
<block type="lists_setIndex">
<mutation at="true"></mutation>
<field name="MODE">SET</field>
<field name="WHERE">FROM_START</field>
<value name="LIST">
<block type="variables_get">
<field name="VAR" id="Jk,w-5|uh#:o4}s(K7F*" variabletype="">list</field>
</block>
</value>
</block>
<block type="lists_getSublist">
<mutation at1="true" at2="true"></mutation>
<field name="WHERE1">FROM_START</field>
<field name="WHERE2">FROM_START</field>
<value name="LIST">
<block type="variables_get">
<field name="VAR" id="Jk,w-5|uh#:o4}s(K7F*" variabletype="">list</field>
</block>
</value>
</block>
<block type="lists_split">
<mutation mode="SPLIT"></mutation>
<field name="MODE">SPLIT</field>
<value name="DELIM">
<shadow type="text">
<field name="TEXT">,</field>
</shadow>
</value>
</block>
<block type="lists_sort">
<field name="TYPE">NUMERIC</field>
<field name="DIRECTION">1</field>
</block>
</category>
<category name="颜色" colour="#A6745C">
<block type="colour_picker">
<field name="COLOUR">#ff0000</field>
</block>
<block type="colour_random"></block>
<block type="colour_rgb">
<value name="RED">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="GREEN">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="BLUE">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>
<block type="colour_blend">
<value name="COLOUR1">
<shadow type="colour_picker">
<field name="COLOUR">#ff0000</field>
</shadow>
</value>
<value name="COLOUR2">
<shadow type="colour_picker">
<field name="COLOUR">#3333ff</field>
</shadow>
</value>
<value name="RATIO">
<shadow type="math_number">
<field name="NUM">0.5</field>
</shadow>
</value>
</block>
</category>
<category name="变量" colour="#A65C81" custom="VARIABLE"></category>
<category name="函数" colour="#9A5CA6" custom="PROCEDURE"></category>
</xml>
</>
)
)
输出js格式的代码
const code_js = Blockly.JavaScript.workspaceToCode(workspace);
console.log('code_js: ', code_js);
输出Python格式的代码
import 'blockly/python';
const code_python = Blockly.Python.workspaceToCode(workspace);
console.log('code_python: ', code_python);
回显保存的block
import 'blockly/blocks';
<!--我们将拖动的块生成代码保存到后端,那么下次我们再打开的话应该回显正确的拼图;但是值提交后端代码是不能回显拼图的,所以就有了相应的xml来回显拼图;-->
<!--提交xml(当前保存在localStorage中)-->
const xml = Blockly.Xml.workspaceToDom(workspace);
const xml_text = Blockly.Xml.domToText(xml);
window.localStorage.setItem('xml_text',xml_text);
<!--回显xml-->
const xml_text = window.localStorage.getItem('xml_text');
const xml = Blockly.Xml.textToDom(xml_text);
Blockly.Xml.domToWorkspace(xml, workspace);
中文支持
import * as Ch from 'blockly/msg/zh-hans';
Blockly.setLocale(Ch);
参考文章
https://developers.google.com/blockly/guides/get-started/web
https://developers.google.com/blockly/guides/configure/web/fixed-size?hl=zh_cn
https://github.com/google/blockly-samples
https://github.com/google/blockly/tree/master/msg/js](https://github.com/google/blockly/tree/master/msg/js)