產生並執行 JavaScript

區塊應用程式通常會產生 JavaScript 做為輸出語言 通常會在網頁中執行 (可能相同或內嵌 WebView)。 和其他產生器一樣,第一步是導入 JavaScript 產生器。

import {javascriptGenerator} from 'blockly/javascript';

如要從工作區產生 JavaScript,請呼叫:

javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);

產生的程式碼可以直接在到達網頁中執行:

try {
  eval(code);
} catch (e) {
  alert(e);
}

基本上,以上程式碼片段只會產生程式碼,並進行評估。不過,我們也做了一些精進。其中一個精進項目是,eval 會包裝在 try/catch 中,以便顯示任何執行階段錯誤,而不會悄悄失敗。另一個修正是將 code 新增至保留清單中 如此一來,如果使用者程式碼中包含該名稱的變數,就會傳回該名稱 物件會自動重新命名,而非設定衝突。任何本機變數都必須 透過這種方式預訂

醒目顯示區塊

在程式碼執行時醒目顯示目前執行的區塊,可協助使用者 瞭解他們的程式行為焦點所在 每個陳述式層級,方法是將 STATEMENT_PREFIX 產生 JavaScript 程式碼:

javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator.addReservedWords('highlightBlock');

定義 highlightBlock 以標記工作區的區塊。

function highlightBlock(id) {
  workspace.highlightBlock(id);
}

這會將 highlightBlock('123'); 陳述式加到 之前 每個陳述式,其中 123 是要替換的區塊序號 醒目顯示。

無限迴圈

雖然產生的程式碼一定會有語法正確的語法 可能包含無限迴圈自 2019 年以來 暫停問題範圍超出 要處理這些案例,區塊範圍 (!) 是最佳做法 如何保留一個計數器,並在每次執行疊代時減少計數器。 如要完成這項操作,只要將 javascriptGenerator.INFINITE_LOOP_TRAP 設為程式碼即可 這段程式碼會插入每個迴圈和每個函式中。以下是 範例:

window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);

範例

這裡是 現場示範 產生及執行 JavaScript

JS 解譯器

如果您很擅長正確執行使用者封鎖程序,那麼 建議您採用 JS-解譯器專案。 這項專案與 Blockly 不同,但是專為 Blockly 編寫。

  • 以任何速度執行程式碼。
  • 暫停/繼續/逐步執行。
  • 在執行時醒目顯示區塊。
  • 與瀏覽器的 JavaScript 完全隔離。

執行翻譯工具

首先,從 GitHub 下載 JS-解譯器:

下載 ZIP 檔案 下載 TAR 球 前往 GitHub 查看

然後新增至頁面:

<script src="acorn_interpreter.js"></script>

呼叫這個方法最簡單的方法,就是產生 JavaScript、建立 並執行程式碼:

var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter.run();

踏出翻譯的第一步

為了放慢程式碼執行速度,或以更多受控的方式執行,請將 利用步驟呼叫 run (本例中每 10 毫秒一個步驟):

function nextStep() {
  if (myInterpreter.step()) {
    setTimeout(nextStep, 10);
  }
}
nextStep();

請注意,每個步驟都不是一行或區塊,而是在 JavaScript,可能會非常精細

新增 API

JS-解譯器是一種完全獨立於瀏覽器之外的沙箱。 凡是對外部執行動作的區塊,都必須將 API 新增至 第一個輸入字詞如需完整說明,請參閱 JS-解譯器說明文件。 不過,我們先來瞭解支援警示和提示區塊所需的 API:

function initApi(interpreter, globalObject) {
  // Add an API function for the alert() block.
  var wrapper = function(text) {
    return alert(arguments.length ? text : '');
  };
  interpreter.setProperty(globalObject, 'alert',
      interpreter.createNativeFunction(wrapper));

  // Add an API function for the prompt() block.
  wrapper = function(text) {
    return prompt(text);
  };
  interpreter.setProperty(globalObject, 'prompt',
      interpreter.createNativeFunction(wrapper));
}

接著,修改翻譯器初始化來傳入 initApi 函式:

var myInterpreter = new Interpreter(code, initApi);

預設封鎖設定中只有兩項封鎖設定 需要自訂 API 才能使用

正在連結「highlightBlock()

在 JS-解譯器中執行時,應執行 highlightBlock() 隨著使用者透過程式執行待辦 這邊建立包裝函式函式 highlightBlock() 來擷取函式 引數並註冊為原生函式。

function initApi(interpreter, globalObject) {
  // Add an API function for highlighting blocks.
  var wrapper = function(id) {
    return workspace.highlightBlock(id);
  };
  interpreter.setProperty(globalObject, 'highlightBlock',
      interpreter.createNativeFunction(wrapper));
}

較複雜的應用程式可能會為了沒有必要而重複執行步驟 暫停,直到聽見醒目顯示指令後暫停。這項策略會模擬 逐行執行。以下範例使用這個方法。

JS-解譯器範例

這裡是 現場示範 這些步驟而這個示範包含等待區塊,是用於其他非同步行為 (例如語音或音訊、使用者輸入) 的絕佳範例。