如何使用 CodeFlask 在 JavaScript 中嵌入代碼編輯器
如何使用 CodeFlask 庫在 Joystick 應用中動態呈現代碼編輯器並檢索其值。
開始使用
在本教程中,我們將使用 CheatCode 的全棧 JavaScript 框架 Joystick。 Joystick 將前端 UI 框架與用於構建應用的 Node.js 後端結合在一起。
首先,我們要通過 NPM 安裝 Joystick。確保在安裝之前使用 Node.js 16+ 以確保兼容性(如果您需要學習如何安裝 Node.js 或在計算機上運行多個版本,請先閱讀本教程):
終端
npm i -g @joystick.js/cli
這將在您的計算機上全局安裝操縱桿。安裝好之後,接下來我們新建一個項目:
終端
joystick create app
幾秒鐘後,您將看到一條消息已註銷到 cd
進入你的新項目並運行 joystick start
.在此之前,我們需要安裝一個依賴項:codeflask
.
終端
npm i codeflask
安裝完成後,繼續啟動您的服務器:
終端
cd app && joystick start
在此之後,您的應用應該可以運行了,我們可以開始了。
編寫一個組件來渲染代碼編輯器
我們在本教程中的所有工作都將在兩個文件中進行。首先,要準備我們的 UI,我們需要在主 index.css
中添加一點 CSS 項目根目錄下的文件(這是一個全局 CSS 文件,由 Joystick 為我們應用中的所有頁面加載):
/index.css
body {
font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
font-size: 16px;
background: #fff;
margin: 0;
padding: 0;
}
我們在此處所做的更改是為 body
的現有 CSS 規則添加了兩個附加屬性 元素:設置margin
到 0
和 padding
到 0
.我們想要這樣做是因為,正如我們將看到的,我們希望我們的代碼編輯器填滿屏幕。如果沒有這兩條線,我們會看到四面都有約 10px 的間隙,看起來像是一個錯誤。
/ui/pages/index/index.js
import ui from '@joystick.js/ui';
const Index = ui.component({
render: () => {
return `
<div>
</div>
`;
},
});
export default Index;
接下來,我們要打開 /ui/pages/index/index.js
處的文件 .該文件代表我們應用程序中的一個頁面(意思是,在我們應用程序的 URL 處呈現的內容)。在裡面,你會發現一些運行 joystick create
時自動生成的示例代碼 .在這裡,我們用一個骨架組件替換了該代碼,我們將在該組件上構建我們的代碼編輯器。
首先,我們想做兩件事:添加我們需要渲染代碼編輯器的基本 HTML 標記和將代碼編輯器注入我們頁面的 JavaScript:
/ui/pages/index/index.js
import ui from '@joystick.js/ui';
import CodeFlask from 'codeflask';
const Index = ui.component({
lifecycle: {
onMount: (component) => {
component.methods.attachCodeEditor(`{}`);
},
},
methods: {
attachCodeEditor: (code = '', component) => {
component.flask = new CodeFlask('#code-editor', {
language: 'js',
defaultTheme: true,
lineNumbers: true,
});
if (code) {
component.flask.updateCode(code);
}
},
},
render: () => {
return `
<div id="code-editor"></div>
`;
},
});
export default Index;
首先,我們要關注render
函數在我們組件的底部。在這裡,我們添加了使代碼編輯器工作所需的基本 HTML:單個 <div></div>
帶有我們可以傳遞給 codeflask
的 ID 的標籤 .
這裡的想法是這個 <div></div>
將作為 codeflask
的目標 將“瞄準”。如果它看到它,它會將代碼編輯器注入到這個 <div></div>
,在屏幕上渲染。
在我們的代碼中,我們可以看到我們已經導入了 CodeFlask
來自 codeflask
包裹。我們使用了這種套管(稱為 Pascal-casing),因為我們期望 codeflask
包以導出 JavaScript 類。通常,我們使用 Pascal-case 來表示一個變量包含 JavaScript 中的一個類。
回到我們的組件,我們添加了一些額外的屬性。首先,在最頂部,我們添加了一個對象 lifecycle
在那個對像上,一個方法 onMount
(方法是 JavaScript 中用於在對像上定義函數的術語)。
那個方法,onMount
, 是 Joystick 在 render
返回的 HTML 之後立即調用的內容 函數被成功渲染或掛載 在屏幕上。在裡面,我們可以看到我們收到了一個參數 component
代表組件實例 ,或者,我們當前正在構建的組件的內存表示。
該實例(一個對象)可以完全訪問我們組件的所有其他屬性。正如我們所見,從該對像中,onMount
我們調用 component.methods.attachCodeEditor()
的方法 .如果我們再往下看,我們可以看到一個 methods
使用 attachCodeEditor
定義的對象 在此定義的方法。這些是同一個。在 onMount
中 ,我們所做的就是調用 attachCodeEditor
methods
上定義的函數 我們組件的對象。
如果我們看一下這個函數,我們可以看到它有兩個參數:code
,我們要在編輯器中呈現的代碼字符串,作為第二個參數,component
.自動在幕後,操縱桿將組件實例作為最後一個參數附加到所有函數。所以,在我們的 onMount
例如,因為沒有參數,component
成為第一個參數。在 attachCodeEditor
,因為我們預計要傳遞一個參數,所以操縱桿分配 component
作為秒 參數,因為這是“最後一個”可能的參數。
attachCodeEditor
內部 ,我們帶來codeflask
混合。在這裡,在 component
例如,我們正在分配一個新屬性 flask
並將其分配給調用 new CodeFlask()
的結果 .我們現在這樣做是為了以後,我們可以引用 CodeFlask
我們組件中其他地方的實例。
到 new CodeFlask()
我們傳遞了兩件事:我們想要用作代碼編輯器的渲染目標的選擇器——在本例中為 ID
<div></div>
我們正在渲染,#code-editor
——還有一個選項對象。
對於我們的選擇,我們保持簡單。這裡,language
表示我們希望在編輯器中輸入的語言。這用於語法高亮(在幕後,codeflask
使用另一個名為 prismjs
的庫 突出顯示/著色我們的代碼,使其更易於閱讀)。
接下來,defaultTheme: true
告訴 codeflask
包括它自己的默認樣式表。雖然您可以編寫自定義樣式表來設置代碼樣式,但根據我們的需要,默認樣式就可以了。
最後,我們通過 lineNumbers: true
在代碼編輯器的左側給我們行號。
一旦我們創建了 codeflask
例如,最後,我們檢查 code
傳遞給 attachCodeEditor
的參數 包含一個真值——意思是,我們傳遞的不僅僅是一個空字符串,這將導致 JavaScript 返回 true
當我們在 if
中引用變量時 陳述——價值。如果它確實 我們要調用 .updateCode()
codeflask
上的方法 我們分配給 component.flask
的實例 .
雖然看起來可能不多,但如果我們在瀏覽器中加載它(作為索引頁面,它將顯示在 http://localhost:2600
在您的瀏覽器中)現在,我們應該看到我們的代碼編輯器呈現在屏幕上。
檢索和驗證代碼編輯器值
雖然我們在技術上“完成”了,但了解如何將代碼編輯器實際用於您自己的應用程序會很有幫助。為了證明這一點,我們將假設我們正在創建 JSON 驗證器。接下來,我們要添加一個函數checkIfValidJSON()
然後將其連接到我們上面編寫的組件。
/lib/checkIfValidJSON.js
export default (string = '') => {
try {
const json = JSON.parse(string);
return !!json;
} catch (exception) {
return false;
}
};
在我們的 /lib
文件夾(我們存儲應用程序的雜項代碼的地方),我們添加了一個文件 checkIfValidJSON.js
它導出一個採用 string
的函數 作為論據。
在該函數內部,我們使用 string
我們將其傳遞給 JSON.parse()
.但是,我們已經將該調用包裝到 JSON.parse()
在 try/catch
. try/catch
說“嘗試運行這段代碼,如果它出於任何原因拋出錯誤,請執行 catch
聲明。”
在這裡,如果 string
我們傳遞給 JSON.parse()
是無效的 JSON,函數會拋出錯誤。在這種情況下,如果它確實 拋出錯誤,我們的 catch
語句將執行並返回 false
從我們導出的函數中。如果它有效 JSON,我們將返回的 json
變量並放置一個 !!
(double-bang) 在它前面將值轉換為布爾值 true
或 false
(如果變量包含一個值,它將是 true
,如果不是,false
)。
/ui/pages/index/index.js
import ui from '@joystick.js/ui';
import CodeFlask from 'codeflask';
import checkIfValidJSON from '../../../lib/checkIfValidJSON';
const Index = ui.component({
state: {
jsonStatus: 'ok',
},
lifecycle: {
onMount: (component) => {
component.methods.attachCodeEditor(`{}`);
},
},
methods: { ... },
css: `
.codeflask {
height: calc(100vh - 91px) !important;
}
header {
display: flex;
align-items: center;
background: #ddd;
color: #333;
padding: 20px;
}
header button {
margin-right: 20px;
height: auto;
font-size: 16px;
padding: 10px 15px;
}
header p.error {
background: yellow;
color: red;
}
header p.ok {
background: yellow;
color: green;
}
`,
events: {
'click .validate-json': (event, component) => {
const json = component.flask.getCode();
const isValidJSON = checkIfValidJSON(json);
if (isValidJSON) {
component.setState({ jsonStatus: 'ok' });
} else {
component.setState({ jsonStatus: 'error' });
}
},
},
render: ({ when, state }) => {
return `
<header>
<button class="validate-json">Validate JSON</button>
${when(state?.jsonStatus === 'error', `<p class="error"><strong>JSON Parse Error</strong> - Please double-check your syntax and try again.</p>`)}
${when(state?.jsonStatus === 'ok', `<p class="ok">Valid JSON!</p>`)}
</header>
<div id="code-editor"></div>
`;
},
});
export default Index;
回到我們的組件中,讓我們使用它。在這裡,我們已經添加了我們需要的所有剩餘代碼。
首先,我們應該解釋我們的目標:我們希望能夠按需驗證我們在代碼編輯器中鍵入的 JSON。為此,我們需要一種“觸發”驗證的方法。在我們的 render
中 在上面的函數中,我們添加了一些額外的 HTML 標記。
我們添加了一個 HTML <header></header>
標籤和里面的 <button></button>
標籤。這裡的想法是當我們點擊 <button></button>
,我們要驗證 JSON 並在 state
上設置一個值 我們組件的價值。那個值,jsonStatus
, 將被設置為包含 error
的字符串 或 ok
.
就在我們渲染 <button></button>
的位置下方 ,我們添加了兩個 JavaScript 插值語句(由 ${}
表示 語法“評估大括號之間的 JavaScript 代碼,然後返回值以將其嵌入到包裝字符串中”),都調用 when()
render 函數作為 Joystick 組件實例的一部分自動傳遞。
訪問該 when()
函數,我們使用 JavaScript 解構來“拔掉”when
和 state
從那個 component
實例對象。需要明確的是,如果我們換一種方式寫,我們可能會看到......
render: (component) => {
return `
<header>
<button class="validate-json">Validate JSON</button>
${component.when(component.state?.jsonStatus === 'error', `<p class="error"><strong>JSON Parse Error</strong> - Please double-check your syntax and try again.</p>`)}
${component.when(component.state?.jsonStatus === 'ok', `<p class="ok">Valid JSON!</p>`)}
</header>
<div id="code-editor"></div>
`;
},
上面的區別在於我們使用解構來創建對值 on 的簡寫引用 component
目的。所以,component
變成 { when, state }
其中 when
和 state
是在 component
上定義的屬性 對象。
/ui/pages/index/index.js
import ui from '@joystick.js/ui';
import CodeFlask from 'codeflask';
import checkIfValidJSON from '../../../lib/checkIfValidJSON';
const Index = ui.component({
state: {
jsonStatus: 'ok',
},
lifecycle: {
onMount: (component) => {
component.methods.attachCodeEditor(`{}`);
},
},
methods: { ... },
css: `
.codeflask {
height: calc(100vh - 91px) !important;
}
header {
display: flex;
align-items: center;
background: #ddd;
color: #333;
padding: 20px;
}
header button {
margin-right: 20px;
height: auto;
font-size: 16px;
padding: 10px 15px;
}
header p.error {
background: yellow;
color: red;
}
header p.ok {
background: yellow;
color: green;
}
`,
events: {
'click .validate-json': (event, component) => {
const json = component.flask.getCode();
const isValidJSON = checkIfValidJSON(json);
if (isValidJSON) {
component.setState({ jsonStatus: 'ok' });
} else {
component.setState({ jsonStatus: 'error' });
}
},
},
render: ({ when, state }) => {
return `
<header>
<button class="validate-json">Validate JSON</button>
${when(state?.jsonStatus === 'error', `<p class="error"><strong>JSON Parse Error</strong> - Please double-check your syntax and try again.</p>`)}
${when(state?.jsonStatus === 'ok', `<p class="ok">Valid JSON!</p>`)}
</header>
<div id="code-editor"></div>
`;
},
});
export default Index;
重新關注我們的插值語句和對 when()
的調用 ,在操縱桿中,“渲染函數”是一個特殊的函數,可以在組件的 render
返回的 HTML 中使用 功能。這裡,when()
是一個渲染函數,它說“當作為我的第一個參數傳遞的值是 true
,返回作為我的第二個參數傳遞的 HTML 字符串——否則,什麼也不返回。”
所以,在這裡,我們說如果 state.jsonStatus
等於 'error'
我們要渲染一個 <p></p>
帶有錯誤消息和 if state.jsonStatus
的標記 等於 ok
,我們要渲染一個 <p></p>
帶有“好的”消息的標籤。默認情況下,在我們組件的頂部,我們添加了一個 state
屬性設置為包含我們組件的默認狀態值的對象。這裡,默認情況下,我們想要 jsonStatus
設置為 ok
.
實際運行我們的驗證(並適當調整此 jsonStatus
value on state),接下來,我們要關注 events
我們添加到組件中的對象。在這裡,我們可以為我們的組件定義 JavaScript 事件偵聽器,即“當您檢測到指定選擇器上指定的事件時,調用此函數。”
在這裡,我們為 click
添加了一個事件監聽器 .validate-json
上的事件 類(記住,我們添加了 validate-json
作為我們 <button></button>
的類 元素在我們的 HTML 標記中)。
單擊該按鈕時,我們要調用我們在此處分配的函數,該函數接受兩個參數:描述事件發生的原始 JavaScript DOM 事件對象和 component
實例(同樣,component
這裡遵循與我們之前描述的相同的邏輯。
在該函數內部,首先,我們需要獲取編輯器的當前值。為此,我們調用 .getCode()
component.flask
上的方法 我們在 attachCodeEditor
中分配的值 上面的方法。這將返回我們編輯器的當前值——不管它是什麼——作為一個字符串。接下來,我們將該字符串交給我們的 checkIfValidJSON()
功能。
請記住:該函數將返回 true
如果我們的 JSON 有效並且 false
如果它無效。在此下方,如果 isValidJSON
是真的,我們調用 setState()
我們組件實例上的方法,設置 jsonStatus
ok
的值 .如果我們的 JSON 無效,我們做同樣的事情,但設置 jsonStatus
到 'error'
.
操縱桿將從這裡接管。現在,當我們改變我們的 jsonStatus
相對於我們從 checkIfValidJSON()
收到的響應的值 , Joystick 將重新渲染我們的組件。就像我們上面討論的那樣,如果 jsonStatus
是 error
我們應該看到我們的錯誤信息被渲染,如果沒問題,我們的“okay”信息。
總結
在本教程中,我們學習瞭如何使用 codeflask
在操縱桿應用程序中呈現代碼編輯器 來自 NPM 的軟件包。我們學習瞭如何在組件中呈現一些 HTML,然後使用 Code Flask 將代碼編輯器動態注入到我們的頁面中。我們還學習瞭如何從代碼編輯器中檢索值並使用它來根據其值控制組件的顯示。