应用设计

在设计使用 Blockly 的应用时,有多种范式可供选择。应尽早考虑这些选择,因为它们会影响用户需要的代码块。

配置

许多 Blockly 应用用于描述配置,而不是可执行程序。配置应用通常通过在工作区中初始化一个根级块来启动。一个很好的例子是 Blockly 开发者工具的“块工厂”标签页:

用于设计其他块的块。用户可以指定块名称、块输入、输入是内部还是外部,等等。

Blockly.Blocks['factory_base'] = {
  init: function() {
    this.setDeletable(false);
    this.setMovable(false);
    this.setEditable(false);
    // etc...
  }
}

Blockly.serialization.blocks.append({'type': 'factory_base'}, workspace);

这会创建一个不可删除、不可移动的块,用于保存所有用户配置。工作区可以随时序列化,以确定当前配置。

此类应用可能希望自动停用未连接到根块的任何块。这可以通过一行代码来实现:

workspace.addChangeListener(Blockly.Events.disableOrphans);

连续剧

大多数 Blockly 应用都旨在创建串行程序。用户将按顺序执行的代码块堆叠在一起。

一叠积木,其中包含移动、左转和再次移动的指令。

工作区上的每个(未停用的)块都将构成程序的一部分。如果有多个块堆栈,则先执行较高的块。(如果两个堆栈的高度大致相同,则优先考虑左侧的堆栈 [在 RTL 模式下为右侧]。)

工作区可以随时导出为可执行代码。此代码可在客户端使用 JavaScript(使用 eval 或 JS 解释器)执行,也可在服务器端使用任何语言执行。

import {javascriptGenerator} from 'blockly/javascript';

var code = javascriptGenerator.workspaceToCode(workspace);

并行计划

有些 Blockly 应用选择并行(而非逐一)执行所有堆叠的块。例如,在音乐应用中,鼓循环与旋律同时运行。

实现并行执行的一种方法是单独为每个块生成代码:

import {javascriptGenerator} from 'blockly/javascript';

var json = Blockly.serialization.workspaces.save(workspace);

// Store top blocks separately, and remove them from the JSON.
var blocks = json['blocks']['blocks'];
var topBlocks = blocks.slice();  // Create shallow copy.
blocks.length = 0;

// Load each block into the workspace individually and generate code.
var allCode = [];
var headless = new Blockly.Workspace();
for (var i = 0; block < topBlocks.length; i++) {
  var block = topBlocks[i];
  blocks.push(block);
  Blockly.serialization.workspaces.load(json, headless);
  allCode.push(javascriptGenerator.workspaceToCode(headless));
  blocks.length = 0;
}

如果目标语言是 JavaScript,则可以使用 allCode 数组创建多个 JS 解释器以供同时执行。如果目标语言是 Python 之类的语言,则可以将 allCode 数组组装成使用线程模块的单个程序。

与任何并行程序一样,必须针对所有共享资源(例如变量和函数)做出谨慎的决策。

事件驱动型程序

事件处理程序只是由系统(而非程序)调用的函数。这些块可以封装要执行的块堆栈,也可以是位于块堆栈顶部的标头。

两个“在点击鼠标时”代码块,一个带有语句输入,另一个带有下一个连接。

有些开发者喜欢在事件块顶部添加“帽子”,使其与其他块区分开来。这不是 Blockly 的默认外观,但可以通过将渲染器常量 ADD_START_HATS 替换为 true自定义渲染器 Codelab - 替换常量)来添加,也可以通过添加主题并设置块样式的帽选项来添加。如需详细了解如何设置块的帽子作为主题的一部分,请参阅主题文档中的块样式

带有帽子的“在点击鼠标时”代码块,帽子在代码块顶部形成一个驼峰。

在事件驱动模型中,为程序启动创建处理程序可能也是合理的。在此模型下,工作区中未连接到事件处理程序的任何块都会被忽略,并且不会执行。

在设计使用事件的系统时,请考虑是否可以或是否需要支持同一事件处理程序的多个实例。

工作区布局

从左到右布局屏幕有两种合理的方式。一种方式是从左侧的工具栏开始,中间是工作区,右侧是输出可视化图表。此布局由 Scratch 版本 1 以及 Made with Code 使用。

一个应用,其中工具栏位于左侧,工作区位于中间,迷宫(输出可视化效果)位于右侧。

另一种方式是从左侧的输出可视化图表开始,中间是工具栏,右侧是工作区。Scratch 版本 2 以及大多数 Blockly 应用都使用此布局。

一个应用,左侧是迷宫(输出可视化效果),中间是工具栏,右侧是工作区。

无论哪种情况,工作区都应拉伸以占据可用的屏幕尺寸,因为用户需要尽可能大的空间来编程。从上面的屏幕截图中可以看出,第一个布局在宽屏上的表现不佳,因为用户的代码和输出可视化效果是分开的。而第二种布局则为较大的节目留出了更多空间,同时仍将所有三个部分紧密地放在一起。

对于用户来说,先考虑要解决的问题,然后查看提供的工具,最后才开始编程,这在逻辑上也是合理的。

当然,对于阿拉伯语和希伯来语翻译,整个顺序都需要颠倒。

在某些情况下(例如使用少量简单代码块时),工具箱位于工作区上方或下方可能更合理。Blockly 支持在工具箱中进行水平滚动,以应对这些情况,但应谨慎使用。

建议:将程序可视化图表放置在工具栏旁边。