即時示例(EmbedLiveSample)
MDN 支援在文章中將程式碼塊顯示為即時示例,這樣讀者可以同時看到原始碼及其在網頁上的輸出。此功能使讀者能夠準確理解執行程式碼會產生什麼效果,使文件更具動態性和教學意義。它還允許作者完全確定文件中的程式碼塊具有預期的輸出,並且在不同瀏覽器中使用時能正常工作。
即時示例系統可以處理用 HTML、CSS 和 JavaScript 編寫的程式碼塊,無論它們在頁面中編寫的順序如何。這確保了輸出與組合後的原始碼相對應,因為系統直接在頁面中執行程式碼。
與互動式示例不同,即時示例不提供內建支援來捕獲控制檯日誌或重置由使用者輸入更改的示例。 示例部分展示瞭如何實現這些以及其他有用的功能。
即時示例如何工作?
即時示例將程式碼塊分組,將它們合併到 HTML 中,並在 <iframe> 中渲染 HTML。一個即時示例由兩部分組成:
- 一個或多個組合在一起的程式碼塊
- 一個宏呼叫,在
<iframe>中顯示程式碼塊的結果
每個包含輸出程式碼的程式碼塊都有一個語言識別符號——html、css 或 js——用於指定它是 HTML、CSS 還是 JavaScript 程式碼。語言識別符號必須在相應的程式碼塊上,並且頁面中必須存在宏呼叫(EmbedLiveSample)才能顯示輸出。
## Examples
```html
<!-- HTML code -->
```
```css
/* CSS code */
```
{{EmbedLiveSample("Examples")}}
即時示例系統允許以不同方式對程式碼塊進行分組,以有效地顯示輸出。下一節將描述這些方法。
分組程式碼塊
程式碼塊可以透過兩種方式分組:
- 使用包含程式碼塊的標題或塊元素的 ID 作為識別符號
- 指定一個字串識別符號以及程式碼塊
預設情況下,未明確指定識別符號的程式碼塊將使用包含程式碼塊的標題或塊元素的 ID 進行分組。在這種情況下,識別符號是標題或塊元素(例如 <div>)的 ID。這在下面的示例中顯示,其中“段落樣式”塊中的 html 和 css 程式碼用於生成 EmbedLiveSample 宏呼叫的輸出。
## Examples
### Styling a paragraph
In this example, we're using CSS to style paragraphs that have the `fancy` class set.
#### HTML
```html
<p>I'm not fancy.</p>
<p class="fancy">But I am!</p>
```
#### CSS
```css
p.fancy {
color: red;
}
```
#### Result
{{EmbedLiveSample("Styling a paragraph")}}
Only the `<p>` element with `class="fancy"` will get styled `red`.
- 如果 ID 屬於塊元素,則該組包含使用其 ID 的封閉塊元素內的所有程式碼塊。
- 如果 ID 屬於某個標題,則該組包含該標題之後且在同一標題級別的下一個標題之前的所有程式碼塊。請注意,指定標題的子標題下的程式碼塊都將使用;如果這不是您想要的效果,請使用塊元素上的 ID 或使用字串識別符號。
要使用識別符號對程式碼塊進行分組,請在程式碼塊的資訊字串中新增格式為 live-sample___{IDENTIFIER} 的字串。識別符號必須是您要分組的程式碼塊的唯一識別符號。例如,live-sample___color-picker 使用 color-picker 作為即時示例系統的識別符號,並且所有資訊字串中包含 live-sample___color-picker 的程式碼塊都將在即時示例中合併。以下示例使用識別符號 color-picker 將 CSS 和 JavaScript 程式碼塊組合在一起。
## Examples
### Styling a paragraph
In this example, we're using CSS to style paragraphs that have the `fancy` class set.
```html live-sample___paragraph-styling
<p>I'm not fancy.</p>
<p class="fancy">But I am!</p>
```
```css live-sample___paragraph-styling
p.fancy {
color: red;
}
```
Only the `<p>` element with `class="fancy"` will get styled `red`:
{{EmbedLiveSample("paragraph-styling")}}
該宏使用一個特殊的 URL,其中包含 ID 以獲取給定程式碼塊組的輸出。您不應在內容中硬編碼此 URL——如果您需要連結到示例,請使用 LiveSampleLink 宏。
生成的框架(或頁面)是沙盒化的,安全的,並且技術上可以做任何在網路上可行的事情。當然,實際上,程式碼應該與頁面內容相關;任何無關材料都可能被 MDN 的編輯社群刪除。
即時示例系統有很多可用的選項,我們將嘗試逐一分解它們。
即時示例宏
您可以使用兩個宏來顯示即時示例:
EmbedLiveSample將即時示例嵌入到頁面中LiveSampleLink建立一個連結,在新頁面中開啟即時示例
在許多情況下,您可能只需很少或無需額外工作即可將 EmbedLiveSample 或 LiveSampleLink 宏新增到頁面!只要示例可以透過標題的 ID 識別,或者位於具有可用 ID 的塊中,新增宏即可完成任務。
EmbedLiveSample 宏
{{EmbedLiveSample(sample_id, width, height, screenshot_URL, page_slug, class_name, allow, sandbox)}}
sample_id-
必填:這可以是示例的字串識別符號,也可以是用於提取程式碼的標題或封閉塊的 ID。要驗證您是否具有正確的標題 ID,請檢視頁面目錄中該部分的 URL;您也可以透過檢視頁面原始碼進行檢查。
width已棄用-
<iframe>的width屬性,以px為單位指定。已廢棄,因為它不再有任何作用:即時示例總是跨內容區域的整個寬度。 height-
<iframe>的height屬性,以px為單位指定。必須至少為60。這是可選的;如果省略,將使用合理的預設高度。 screenshot_URL已廢棄-
顯示即時示例應有的外觀的螢幕截圖的 URL。已廢棄;僅在有合理的瀏覽器支援時才新增即時示例。
page_slug已廢棄-
包含示例的頁面的 slug;這是可選的,如果未提供,則從使用宏的同一頁面中提取示例。已廢棄;僅當代碼在同一頁面上時才包含即時示例。
class_name已廢棄-
要應用於
<iframe>的類名。已廢棄;沒有理由使用其他類名。 allow-
<iframe>的allow屬性。這是可選的;預設情況下不包含任何允許的功能。 sandbox-
一個字串,包含示例應包含的
sandbox屬性。允許的值有allow-modals、allow-forms和allow-popups。可以提供多個值,例如"allow-modals allow-popups"。
LiveSampleLink 宏
{{LiveSampleLink(block_ID, link_text)}}
使用即時示例系統
以下部分描述了即時示例系統的幾個常見用例。
格式化即時示例
如果您在“示例”部分編寫即時示例,請為該即時示例提供描述性的 H3 標題(###)。理想情況下,編寫一個簡短的示例描述,解釋場景以及您希望演示的內容。然後按照以下列出的順序新增帶有 H4 標題(####)的子部分:
- HTML
- CSS
- JavaScript
- 結果
在上面列出的相應子部分中編寫程式碼塊。
在結果子部分中,新增對 EmbedLiveSample 宏的呼叫。最好在該子部分中包含一些額外的散文來描述結果。
如果您不使用特定的語言型別(例如,如果您不使用 JavaScript)或者您正在隱藏程式碼塊,那麼您應該省略相應的標題。
隱藏程式碼
有時您只想顯示與頁面中渲染的示例相關的靜態程式碼塊。但是,您仍然需要 HTML、CSS 和 JavaScript 程式碼塊來渲染這樣的示例。
要實現此目的,您可以透過向語言識別符號新增 hidden 資訊字串來隱藏任何不相關的程式碼塊。如果您這樣做,請省略隱藏程式碼塊的 ### HTML/CSS/JavaScript 標題。
使用上面的示例,但隱藏 HTML 程式碼將如下所示:
## Examples
### Styling a paragraph
In this example, we're using CSS to style paragraphs that have the `fancy` class set.
```html hidden
<p>I'm not fancy.</p>
<p class="fancy">But I am!</p>
```
#### CSS
```css
p.fancy {
color: red;
}
```
#### Result
Only the `<p>` element with `class="fancy"` will get styled `red`.
{{EmbedLiveSample("Styling a paragraph")}}
將片段轉換為即時示例
一個常見的用例是將 MDN 上已有的現有程式碼片段轉換為即時示例。第一步是新增程式碼片段或確保現有程式碼片段在內容和標記方面都已準備好用作即時示例。這些程式碼片段必須共同組成一個完整、可執行的示例。例如,如果現有片段只顯示 CSS,您可能需要新增一個 HTML 片段供 CSS 操作。
每段程式碼必須位於一個程式碼塊中,每種語言一個單獨的塊,並正確標記其語言型別。大多數情況下,這已經完成,但始終值得仔細檢查以確保每段程式碼都配置了正確的語法。這是透過在程式碼塊上使用 language-type 語言識別符號來完成的,其中 language-type 是塊包含的語言型別,例如 html、css 或 js。
注意:每種語言可以有多個塊;它們都被連線在一起。這允許您有一段程式碼,然後是對其工作原理的解釋,然後是另一段程式碼,依此類推。這使得製作利用穿插有解釋性文字的即時示例的教程等內容變得更加容易。
因此,請確保您的 HTML、CSS 和/或 JavaScript 程式碼塊都已正確配置其語言的語法高亮顯示,然後您就可以開始了。
示例
本節包含示例,展示瞭如何使用即時示例系統,包括對組成示例的程式碼塊進行分組的不同方式,以及如何在示例中顯示日誌輸出。
請注意,程式碼塊的標題(“HTML”、“CSS”或“JavaScript”)在大多數 MDN 示例中都是約定俗成的用法,但實際上並非即時示例宏所必需。
按標題分組程式碼塊
HTML
此 HTML 建立一個段落和一些塊,以幫助我們定位和設定訊息的樣式。
<p>A simple example of the live sample system in action.</p>
<div class="box">
<div id="item">Hello world! Welcome to MDN</div>
</div>
CSS
CSS 程式碼設定框的樣式以及其中的文字。
.box {
width: 200px;
border-radius: 6px;
padding: 20px;
background-color: #ffaabb;
}
#item {
font-weight: bold;
text-align: center;
font-family: sans-serif;
font-size: 1.5em;
}
JavaScript
在 JavaScript 示例中,我們向“Hello world!”文字附加了一個事件處理程式,當點選時會切換它。
const el = document.getElementById("item");
let toggleClick = false;
el.onclick = function () {
this.textContent = toggleClick
? "Hello world! Welcome to MDN"
: "Owww, stop poking me!";
toggleClick = !toggleClick;
};
結果
這是透過 {{EmbedLiveSample('grouping_code_blocks_by_heading')}} 執行以上程式碼塊的結果
這是透過 {{LiveSampleLink('grouping_code_blocks_by_heading', '即時示例演示連結')}} 呼叫這些程式碼塊生成的連結
按識別符號分組程式碼塊
此 HTML 建立一個段落和一些塊,以幫助我們定位和設定訊息的樣式。字串 live-sample___hello-world 已新增到此程式碼塊的 html 語言識別符號中。
<p>A simple example of the live sample system in action.</p>
<div class="box">
<div id="item">Hello world! Welcome to MDN</div>
</div>
CSS 程式碼設定框的樣式以及其中的文字。字串 live-sample___hello-world 已新增到此程式碼塊的 css 語言識別符號中。
.box {
width: 200px;
border-radius: 6px;
padding: 20px;
background-color: #ffaabb;
}
#item {
font-weight: bold;
text-align: center;
font-family: sans-serif;
font-size: 1.5em;
}
此 JavaScript 程式碼向“Hello world!”文字附加了一個事件處理程式,當點選時會切換它。字串 live-sample___hello-world 也已新增到此程式碼塊的 js 語言識別符號中。
const el = document.getElementById("item");
let toggleClick = false;
el.onclick = function () {
this.textContent = toggleClick
? "Hello world! Welcome to MDN"
: "Owww, stop poking me!";
toggleClick = !toggleClick;
};
我們透過在 {{EmbedLiveSample('hello-world')}} 宏呼叫中使用字串識別符號 hello-world 執行以上程式碼塊獲得此輸出
顯示特定大小的 <iframe>
使用 height 引數指定包含即時示例輸出的 <iframe> 元素的大小。
<p>Just some simple text here.</p>
{{EmbedLiveSample("iframe_size", "", "60")}} 的結果
{{EmbedLiveSample("iframe_size", "", "120")}} 的結果
允許的功能
allow 引數可用於指定包含即時示例輸出的 <iframe> 元素中允許的功能。可用值來自框架的許可權策略語法。
<div id="fullscreen-content">
<button id="toggle-btn">Toggle fullscreen</button>
</div>
const toggleBtn = document.getElementById("toggle-btn");
const fullscreenContent = document.getElementById("fullscreen-content");
toggleBtn.addEventListener("click", () => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
fullscreenContent.requestFullscreen();
}
});
{{EmbedLiveSample("allowing_features", "", "60", "", "", "", "fullscreen")}} 的結果
{{EmbedLiveSample("allowing_features", "", "60")}} 的結果
顯示單條日誌
此示例展示瞭如何在即時示例中實現簡單的單條日誌,每次新增新的日誌條目時,都會替換先前的值。
為了清晰起見,此示例將日誌程式碼和使用它的程式碼分開,並首先顯示日誌程式碼。通常,在實現自己的示例時,應將日誌元素放置在其他 UI 元素下方。
注意:將日誌輸出作為示例的一部分顯示比使用 console.log() 提供更好的使用者體驗。
HTML
建立一個 id 為 "log" 的 <pre> 元素,用於顯示日誌輸出。
<pre id="log"></pre>
JavaScript
接下來定義日誌函式 log()。它以要記錄的文字作為引數,並用它替換現有日誌。
const logElement = document.querySelector("#log");
function log(text) {
logElement.innerText = text;
}
請注意,日誌元素的內容是使用 innerText 屬性設定的,這比使用 innerHTML 更安全,因為記錄的文字不會被解析為 HTML(這可能會注入惡意程式碼)。
CSS
CSS 設定日誌元素的高度。
#log {
height: 20px;
}
日誌測試程式碼
此示例旨在展示“如何記錄”,因此“記錄什麼”並不那麼重要。因此,它被簡單地實現為一個按鈕,使用者可以按下該按鈕來增加值。
<button id="increment" type="button">Press me many times</button>
const incrementButton = document.querySelector("#increment");
let incrementValue = 0;
incrementButton.addEventListener("click", () => {
incrementValue++;
log(`The button has been pressed ${incrementValue} time(s)`);
});
結果
按下按鈕以新增新的日誌內容。
顯示追加專案的日誌
此示例展示瞭如何在即時示例中實現一個簡單的“日誌控制檯”。每次新增日誌時,控制檯都會在輸出末尾追加新行,並將新專案滾動到檢視中。
為了清晰起見,此示例將日誌程式碼和使用它的程式碼分開,並首先顯示日誌程式碼。通常,在實現自己的示例時,應將日誌元素放置在其他 UI 元素下方。
注意:將日誌輸出作為示例的一部分顯示比使用 console.log() 提供更好的使用者體驗。
有關更完整的示例,請參閱 DataTransfer.effectAllowed。
HTML
建立一個 id 為 "log" 的 <pre> 元素,用於顯示日誌輸出。
<pre id="log"></pre>
JavaScript
接下來定義日誌函式 log()。它以要記錄的文字作為引數,並將其作為新行追加到日誌元素中的內容。該函式還將元素 scrollTop 設定為元素的 scrollHeight,這會強制將新行日誌文字滾動到檢視中。
const logElement = document.querySelector("#log");
function log(text) {
logElement.innerText = `${logElement.innerText}${text}\n`;
logElement.scrollTop = logElement.scrollHeight;
}
與上一個示例一樣,我們使用 innerText 屬性設定內容,因為這比使用 innerHTML 更不容易受到惡意程式碼的影響。
CSS
CSS 在元素內容溢位時新增捲軸,設定日誌元素的高度,並新增邊框。請注意,上面的 JavaScript 確保如果溢位,新增新的日誌文字將使文字滾動到檢視中。
#log {
height: 100px;
overflow: scroll;
padding: 0.5rem;
border: 1px solid black;
}
日誌測試程式碼
此示例旨在展示“如何記錄”,因此“記錄什麼”並不那麼重要。因此,它被簡單地實現為一個按鈕,使用者可以按下該按鈕來增加值。
<button id="increment" type="button">Press me many times</button>
const incrementButton = document.querySelector("#increment");
let incrementValue = 0;
incrementButton.addEventListener("click", () => {
incrementValue++;
log(`The button has been pressed ${incrementValue} time(s)`);
});
結果
按下按鈕以新增新的日誌內容。
顯示重置按鈕
重置按鈕對於無法在不重置頁面的情況下恢復到初始狀態的示例很有幫助。例如,Highlight.priority“設定優先順序”示例需要一個重置按鈕,因為一旦您設定了任一優先順序,初始狀態就不可用了。
此示例展示瞭如何向上面顯示追加專案的日誌示例新增重置按鈕。請注意,日誌程式碼的 JavaScript 和 CSS 與上一個示例相同,因此該程式碼是隱藏的。
HTML
示例的 HTML 現在包含一個重置按鈕。
<button id="increment" type="button">Press me many times</button>
<button id="reset" type="button">Reset</button>
<pre id="log"></pre>
JavaScript
按鈕的程式碼添加了一個 click 事件處理函式,該函式只是重新載入包含當前示例的框架。
const reload = document.querySelector("#reset");
reload.addEventListener("click", () => {
window.location.reload(true);
});
結果
多次點選“多次按下我”按鈕。透過按下“重置”按鈕重置示例。
關於即時示例的約定
- 程式碼塊的順序
-
新增即時示例時,程式碼塊應排序,以便第一個程式碼塊對應於此示例的主要語言(如果存在)。例如,為 HTML 參考新增即時示例時,第一個塊應為 HTML;為 CSS 參考新增即時示例時,應為 CSS,依此類推。
- 標題命名
-
當沒有歧義時(例如,示例在“示例”部分下),標題應直接使用相應語言的名稱:HTML、CSS、JavaScript、SVG 等(見上文)。不應使用“HTML 內容”或“JavaScript 內容”之類的標題。但是,如果這樣的短標題使內容不清楚,則可以使用更周到的標題。
- 使用“結果”塊
-
在不同的程式碼塊之後,請在使用
EmbedLiveSample宏之前使用最後一個“結果”塊(見上文)。這樣,示例的語義對於讀者和任何解析頁面的工具(例如,螢幕閱讀器、網路爬蟲)都更加清晰。