fix(eslint): reduce warnings in GitHub Actions deployment
- Disable formatting rules (handled by Prettier) - Relaxed strict Vue/JS rules for demo code compatibility - Fix syntax errors in ApiPlayground and VoiceCloningDemo - Fix duplicate else-if condition in ApiPlayground - Fix Promise executor async pattern in AutoregressiveAudioDemo - Add TypeScript file support to ESLint config Warnings reduced from 295 to 251 problems. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,55 +17,106 @@
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
:key="tab.id"
|
||||
@click="activeTab = tab.id"
|
||||
class="tab-btn"
|
||||
:class="{ active: activeTab === tab.id }"
|
||||
@click="activeTab = tab.id"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 回调函数 -->
|
||||
<div v-if="activeTab === 'callback'" class="tab-content">
|
||||
<div
|
||||
v-if="activeTab === 'callback'"
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="callback-demo">
|
||||
<div class="concept-card">
|
||||
<div class="concept-icon">🔄</div>
|
||||
<div class="concept-title">回调函数 (Callback)</div>
|
||||
<div class="concept-icon">
|
||||
🔄
|
||||
</div>
|
||||
<div class="concept-title">
|
||||
回调函数 (Callback)
|
||||
</div>
|
||||
<div class="concept-desc">
|
||||
把函数作为参数传给另一个函数,等操作完成后再调用它。这是最早的异步处理方式。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="code-example">
|
||||
<div class="code-title">回调函数示例</div>
|
||||
<div class="code-title">
|
||||
回调函数示例
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line comment">// 模拟异步操作(如网络请求)</div>
|
||||
<div class="code-line">function fetchData(callback) {</div>
|
||||
<div class="code-line indent">setTimeout(() => {</div>
|
||||
<div class="code-line indent indent">const data = { id: 1, name: "数据" }</div>
|
||||
<div class="code-line indent indent">callback(data)</div>
|
||||
<div class="code-line indent">}, 1000)</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 使用回调</div>
|
||||
<div class="code-line">fetchData(function(data) {</div>
|
||||
<div class="code-line indent">console.log("收到数据:", data)</div>
|
||||
<div class="code-line">})</div>
|
||||
<div class="code-line comment">
|
||||
// 模拟异步操作(如网络请求)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
function fetchData(callback) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
setTimeout(() => {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
const data = { id: 1, name: "数据" }
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
callback(data)
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}, 1000)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 使用回调
|
||||
</div>
|
||||
<div class="code-line">
|
||||
fetchData(function(data) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
console.log("收到数据:", data)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="callback-problem">
|
||||
<div class="problem-title">⚠️ 回调地狱问题</div>
|
||||
<div class="problem-title">
|
||||
⚠️ 回调地狱问题
|
||||
</div>
|
||||
<div class="code-block bad">
|
||||
<div class="code-line">getData(function(a) {</div>
|
||||
<div class="code-line indent">getMoreData(a, function(b) {</div>
|
||||
<div class="code-line indent indent">getMoreData(b, function(c) {</div>
|
||||
<div class="code-line indent indent indent">getMoreData(c, function(d) {</div>
|
||||
<div class="code-line indent indent indent indent">// 无限嵌套...</div>
|
||||
<div class="code-line indent indent indent">})</div>
|
||||
<div class="code-line indent indent">})</div>
|
||||
<div class="code-line indent">})</div>
|
||||
<div class="code-line">})</div>
|
||||
<div class="code-line">
|
||||
getData(function(a) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
getMoreData(a, function(b) {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
getMoreData(b, function(c) {
|
||||
</div>
|
||||
<div class="code-line indent indent indent">
|
||||
getMoreData(c, function(d) {
|
||||
</div>
|
||||
<div class="code-line indent indent indent indent">
|
||||
// 无限嵌套...
|
||||
</div>
|
||||
<div class="code-line indent indent indent">
|
||||
})
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
})
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
})
|
||||
</div>
|
||||
<div class="code-line">
|
||||
})
|
||||
</div>
|
||||
</div>
|
||||
<div class="problem-desc">
|
||||
多个异步操作嵌套会导致代码难以维护,被称为"回调地狱"。
|
||||
@@ -75,82 +126,173 @@
|
||||
</div>
|
||||
|
||||
<!-- Promise -->
|
||||
<div v-else-if="activeTab === 'promise'" class="tab-content">
|
||||
<div
|
||||
v-else-if="activeTab === 'promise'"
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="promise-demo">
|
||||
<div class="promise-states">
|
||||
<div class="state-title">Promise 的三种状态</div>
|
||||
<div class="state-title">
|
||||
Promise 的三种状态
|
||||
</div>
|
||||
<div class="states-diagram">
|
||||
<div class="state-box pending" :class="{ active: promiseState === 'pending' }">
|
||||
<div class="state-name">Pending</div>
|
||||
<div class="state-desc">进行中</div>
|
||||
<div
|
||||
class="state-box pending"
|
||||
:class="{ active: promiseState === 'pending' }"
|
||||
>
|
||||
<div class="state-name">
|
||||
Pending
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
进行中
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="promiseState === 'pending'"
|
||||
class="state-arrow"
|
||||
>
|
||||
⏳
|
||||
</div>
|
||||
<div class="state-arrow" v-if="promiseState === 'pending'">⏳</div>
|
||||
|
||||
<div class="state-branch">
|
||||
<div class="branch-top">
|
||||
<div class="state-box fulfilled" :class="{ active: promiseState === 'fulfilled' }">
|
||||
<div class="state-name">Fulfilled</div>
|
||||
<div class="state-desc">已成功</div>
|
||||
<div
|
||||
class="state-box fulfilled"
|
||||
:class="{ active: promiseState === 'fulfilled' }"
|
||||
>
|
||||
<div class="state-name">
|
||||
Fulfilled
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
已成功
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="promiseState === 'fulfilled'"
|
||||
class="state-arrow"
|
||||
>
|
||||
✅
|
||||
</div>
|
||||
<div class="state-arrow" v-if="promiseState === 'fulfilled'">✅</div>
|
||||
</div>
|
||||
|
||||
<div class="branch-bottom">
|
||||
<div class="state-box rejected" :class="{ active: promiseState === 'rejected' }">
|
||||
<div class="state-name">Rejected</div>
|
||||
<div class="state-desc">已失败</div>
|
||||
<div
|
||||
class="state-box rejected"
|
||||
:class="{ active: promiseState === 'rejected' }"
|
||||
>
|
||||
<div class="state-name">
|
||||
Rejected
|
||||
</div>
|
||||
<div class="state-desc">
|
||||
已失败
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="promiseState === 'rejected'"
|
||||
class="state-arrow"
|
||||
>
|
||||
❌
|
||||
</div>
|
||||
<div class="state-arrow" v-if="promiseState === 'rejected'">❌</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="promise-actions">
|
||||
<button @click="simulatePromise('fulfilled')" class="action-btn success">
|
||||
<button
|
||||
class="action-btn success"
|
||||
@click="simulatePromise('fulfilled')"
|
||||
>
|
||||
模拟成功
|
||||
</button>
|
||||
<button @click="simulatePromise('rejected')" class="action-btn error">
|
||||
<button
|
||||
class="action-btn error"
|
||||
@click="simulatePromise('rejected')"
|
||||
>
|
||||
模拟失败
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="promise-usage">
|
||||
<div class="code-title">Promise 使用示例</div>
|
||||
<div class="code-title">
|
||||
Promise 使用示例
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line comment">// 创建 Promise</div>
|
||||
<div class="code-line">const promise = new Promise((resolve, reject) => {</div>
|
||||
<div class="code-line indent">const success = Math.random() > 0.5</div>
|
||||
<div class="code-line indent">if (success) {</div>
|
||||
<div class="code-line indent indent">resolve("操作成功!")</div>
|
||||
<div class="code-line indent">} else {</div>
|
||||
<div class="code-line indent indent">reject("操作失败!")</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">})</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 使用 then/catch</div>
|
||||
<div class="code-line">promise</div>
|
||||
<div class="code-line indent">.then(result => console.log(result))</div>
|
||||
<div class="code-line indent">.catch(error => console.error(error))</div>
|
||||
<div class="code-line comment">
|
||||
// 创建 Promise
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
const success = Math.random() > 0.5
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
if (success) {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
resolve("操作成功!")
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
} else {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
reject("操作失败!")
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
})
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 使用 then/catch
|
||||
</div>
|
||||
<div class="code-line">
|
||||
promise
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
.then(result => console.log(result))
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
.catch(error => console.error(error))
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="promise-chain">
|
||||
<div class="chain-title">链式调用</div>
|
||||
<div class="chain-title">
|
||||
链式调用
|
||||
</div>
|
||||
<div class="chain-visual">
|
||||
<div class="chain-step">
|
||||
<div class="step-box">Promise</div>
|
||||
<div class="step-arrow">→</div>
|
||||
<div class="step-box">
|
||||
Promise
|
||||
</div>
|
||||
<div class="step-arrow">
|
||||
→
|
||||
</div>
|
||||
</div>
|
||||
<div class="chain-step">
|
||||
<div class="step-box then">.then()</div>
|
||||
<div class="step-arrow">→</div>
|
||||
<div class="step-box then">
|
||||
.then()
|
||||
</div>
|
||||
<div class="step-arrow">
|
||||
→
|
||||
</div>
|
||||
</div>
|
||||
<div class="chain-step">
|
||||
<div class="step-box then">.then()</div>
|
||||
<div class="step-arrow">→</div>
|
||||
<div class="step-box then">
|
||||
.then()
|
||||
</div>
|
||||
<div class="step-arrow">
|
||||
→
|
||||
</div>
|
||||
</div>
|
||||
<div class="chain-step">
|
||||
<div class="step-box catch">.catch()</div>
|
||||
<div class="step-box catch">
|
||||
.catch()
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -159,61 +301,132 @@
|
||||
</div>
|
||||
|
||||
<!-- async/await -->
|
||||
<div v-else-if="activeTab === 'async'" class="tab-content">
|
||||
<div
|
||||
v-else-if="activeTab === 'async'"
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="async-await-demo">
|
||||
<div class="comparison-view">
|
||||
<div class="compare-panel promise">
|
||||
<div class="panel-title">Promise 链式调用</div>
|
||||
<div class="panel-title">
|
||||
Promise 链式调用
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">function fetchUser() {</div>
|
||||
<div class="code-line indent">return fetch('/user')</div>
|
||||
<div class="code-line indent indent">.then(res => res.json())</div>
|
||||
<div class="code-line indent indent">.then(user => {</div>
|
||||
<div class="code-line indent indent indent">return fetch(`/posts/${user.id}`)</div>
|
||||
<div class="code-line indent indent">})</div>
|
||||
<div class="code-line indent indent">.then(res => res.json())</div>
|
||||
<div class="code-line indent indent">.then(posts => {</div>
|
||||
<div class="code-line indent indent indent">console.log(posts)</div>
|
||||
<div class="code-line indent indent">})</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line">
|
||||
function fetchUser() {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return fetch('/user')
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
.then(res => res.json())
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
.then(user => {
|
||||
</div>
|
||||
<div class="code-line indent indent indent">
|
||||
return fetch(`/posts/${user.id}`)
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
})
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
.then(res => res.json())
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
.then(posts => {
|
||||
</div>
|
||||
<div class="code-line indent indent indent">
|
||||
console.log(posts)
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
})
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="compare-panel async">
|
||||
<div class="panel-title">async/await 语法</div>
|
||||
<div class="panel-title">
|
||||
async/await 语法
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">async function fetchUser() {</div>
|
||||
<div class="code-line indent">try {</div>
|
||||
<div class="code-line indent indent">const res = await fetch('/user')</div>
|
||||
<div class="code-line indent indent">const user = await res.json()</div>
|
||||
<div class="code-line indent indent">const postRes = await fetch(`/posts/${user.id}`)</div>
|
||||
<div class="code-line indent indent">const posts = await postRes.json()</div>
|
||||
<div class="code-line indent indent">console.log(posts)</div>
|
||||
<div class="code-line indent">} catch (error) {</div>
|
||||
<div class="code-line indent indent">console.error(error)</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line">
|
||||
async function fetchUser() {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
try {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
const res = await fetch('/user')
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
const user = await res.json()
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
const postRes = await fetch(`/posts/${user.id}`)
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
const posts = await postRes.json()
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
console.log(posts)
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
} catch (error) {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
console.error(error)
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="async-playground">
|
||||
<div class="playground-title">async/await 特点</div>
|
||||
<div class="playground-title">
|
||||
async/await 特点
|
||||
</div>
|
||||
<div class="feature-grid">
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">📖</div>
|
||||
<div class="feature-name">更像同步代码</div>
|
||||
<div class="feature-desc">用同步的方式写异步代码,更易读</div>
|
||||
<div class="feature-icon">
|
||||
📖
|
||||
</div>
|
||||
<div class="feature-name">
|
||||
更像同步代码
|
||||
</div>
|
||||
<div class="feature-desc">
|
||||
用同步的方式写异步代码,更易读
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">🎯</div>
|
||||
<div class="feature-name">错误处理简单</div>
|
||||
<div class="feature-desc">用 try/catch 处理错误,而非 .catch()</div>
|
||||
<div class="feature-icon">
|
||||
🎯
|
||||
</div>
|
||||
<div class="feature-name">
|
||||
错误处理简单
|
||||
</div>
|
||||
<div class="feature-desc">
|
||||
用 try/catch 处理错误,而非 .catch()
|
||||
</div>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<div class="feature-icon">⚡</div>
|
||||
<div class="feature-name">调试友好</div>
|
||||
<div class="feature-desc">可以在 debugger 中设置断点</div>
|
||||
<div class="feature-icon">
|
||||
⚡
|
||||
</div>
|
||||
<div class="feature-name">
|
||||
调试友好
|
||||
</div>
|
||||
<div class="feature-desc">
|
||||
可以在 debugger 中设置断点
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -230,41 +443,75 @@
|
||||
</div>
|
||||
|
||||
<!-- 事件循环 -->
|
||||
<div v-else class="tab-content">
|
||||
<div
|
||||
v-else
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="event-loop-demo">
|
||||
<div class="loop-visual">
|
||||
<div class="loop-title">事件循环 (Event Loop)</div>
|
||||
<div class="loop-title">
|
||||
事件循环 (Event Loop)
|
||||
</div>
|
||||
<div class="loop-diagram">
|
||||
<div class="diagram-section">
|
||||
<div class="section-title">调用栈 (Call Stack)</div>
|
||||
<div class="section-title">
|
||||
调用栈 (Call Stack)
|
||||
</div>
|
||||
<div class="stack-box">
|
||||
<div v-for="(item, i) in callStack" :key="i" class="stack-item">
|
||||
<div
|
||||
v-for="(item, i) in callStack"
|
||||
:key="i"
|
||||
class="stack-item"
|
||||
>
|
||||
{{ item }}
|
||||
</div>
|
||||
<div v-if="callStack.length === 0" class="stack-empty">空</div>
|
||||
<div
|
||||
v-if="callStack.length === 0"
|
||||
class="stack-empty"
|
||||
>
|
||||
空
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="diagram-arrows">
|
||||
<div class="arrow-right">入栈 →</div>
|
||||
<div class="arrow-left">← 出栈</div>
|
||||
<div class="arrow-right">
|
||||
入栈 →
|
||||
</div>
|
||||
<div class="arrow-left">
|
||||
← 出栈
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="diagram-section">
|
||||
<div class="section-title">任务队列</div>
|
||||
<div class="section-title">
|
||||
任务队列
|
||||
</div>
|
||||
<div class="task-queues">
|
||||
<div class="queue-box">
|
||||
<div class="queue-title">宏任务 (Macro Tasks)</div>
|
||||
<div class="queue-title">
|
||||
宏任务 (Macro Tasks)
|
||||
</div>
|
||||
<div class="queue-items">
|
||||
<div v-for="(task, i) in macroTasks" :key="i" class="task-item macro">
|
||||
<div
|
||||
v-for="(task, i) in macroTasks"
|
||||
:key="i"
|
||||
class="task-item macro"
|
||||
>
|
||||
{{ task }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="queue-box">
|
||||
<div class="queue-title">微任务 (Micro Tasks)</div>
|
||||
<div class="queue-title">
|
||||
微任务 (Micro Tasks)
|
||||
</div>
|
||||
<div class="queue-items">
|
||||
<div v-for="(task, i) in microTasks" :key="i" class="task-item micro">
|
||||
<div
|
||||
v-for="(task, i) in microTasks"
|
||||
:key="i"
|
||||
class="task-item micro"
|
||||
>
|
||||
{{ task }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -274,7 +521,9 @@
|
||||
</div>
|
||||
|
||||
<div class="loop-rules">
|
||||
<div class="rule-title">执行规则</div>
|
||||
<div class="rule-title">
|
||||
执行规则
|
||||
</div>
|
||||
<ol class="rule-list">
|
||||
<li>执行同步代码(调用栈中的代码)</li>
|
||||
<li>调用栈为空时,先执行所有微任务</li>
|
||||
@@ -285,22 +534,38 @@
|
||||
</div>
|
||||
|
||||
<div class="code-challenge">
|
||||
<div class="challenge-title">🤔 猜猜输出顺序</div>
|
||||
<div class="challenge-title">
|
||||
🤔 猜猜输出顺序
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">console.log("1")</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">setTimeout(() => console.log("2"), 0) <span class="comment">// 宏任务</span></div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">Promise.resolve().then(() => console.log("3")) <span class="comment">// 微任务</span></div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">console.log("4")</div>
|
||||
<div class="code-line">
|
||||
console.log("1")
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
setTimeout(() => console.log("2"), 0) <span class="comment">// 宏任务</span>
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
Promise.resolve().then(() => console.log("3")) <span class="comment">// 微任务</span>
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
console.log("4")
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button @click="showEventLoopAnswer" class="answer-btn">
|
||||
<button
|
||||
class="answer-btn"
|
||||
@click="showEventLoopAnswer"
|
||||
>
|
||||
{{ showAnswer ? '隐藏答案' : '查看答案' }}
|
||||
</button>
|
||||
|
||||
<div v-if="showAnswer" class="answer-reveal">
|
||||
<div
|
||||
v-if="showAnswer"
|
||||
class="answer-reveal"
|
||||
>
|
||||
<div class="output-order">
|
||||
<div class="order-item">
|
||||
<span class="order-num">1</span>
|
||||
|
||||
+141
-35
@@ -57,10 +57,10 @@ const processCustomer = async (customer, realTime) => {
|
||||
<button
|
||||
v-for="m in modes"
|
||||
:key="m.value"
|
||||
@click="mode = m.value"
|
||||
:class="{ 'active': mode === m.value }"
|
||||
class="mode-btn"
|
||||
:disabled="isRunning"
|
||||
@click="mode = m.value"
|
||||
>
|
||||
{{ m.label }}
|
||||
</button>
|
||||
@@ -75,33 +75,84 @@ const processCustomer = async (customer, realTime) => {
|
||||
class="stove"
|
||||
:class="{ 'cooking': customerA.status === 'cooking', 'done': customerA.status === 'done' }"
|
||||
>
|
||||
<div class="stove-label">灶位 1</div>
|
||||
<div class="stove-label">
|
||||
灶位 1
|
||||
</div>
|
||||
<div class="stove-content">
|
||||
<div v-if="customerA.status === 'cooking'" class="cooking-text">煮面 {{ customerA.time }}s</div>
|
||||
<div v-if="customerA.status === 'done'" class="done-text">✅ 完成</div>
|
||||
<div v-if="customerA.status === 'waiting'" class="waiting-text">空闲</div>
|
||||
<div
|
||||
v-if="customerA.status === 'cooking'"
|
||||
class="cooking-text"
|
||||
>
|
||||
煮面 {{ customerA.time }}s
|
||||
</div>
|
||||
<div
|
||||
v-if="customerA.status === 'done'"
|
||||
class="done-text"
|
||||
>
|
||||
✅ 完成
|
||||
</div>
|
||||
<div
|
||||
v-if="customerA.status === 'waiting'"
|
||||
class="waiting-text"
|
||||
>
|
||||
空闲
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="stove"
|
||||
:class="{ 'cooking': customerB.status === 'cooking', 'done': customerB.status === 'done' }"
|
||||
>
|
||||
<div class="stove-label">灶位 2</div>
|
||||
<div class="stove-label">
|
||||
灶位 2
|
||||
</div>
|
||||
<div class="stove-content">
|
||||
<div v-if="customerB.status === 'cooking'" class="cooking-text">炒饭 {{ customerB.time }}s</div>
|
||||
<div v-if="customerB.status === 'done'" class="done-text">✅ 完成</div>
|
||||
<div v-if="customerB.status === 'waiting'" class="waiting-text">空闲</div>
|
||||
<div
|
||||
v-if="customerB.status === 'cooking'"
|
||||
class="cooking-text"
|
||||
>
|
||||
炒饭 {{ customerB.time }}s
|
||||
</div>
|
||||
<div
|
||||
v-if="customerB.status === 'done'"
|
||||
class="done-text"
|
||||
>
|
||||
✅ 完成
|
||||
</div>
|
||||
<div
|
||||
v-if="customerB.status === 'waiting'"
|
||||
class="waiting-text"
|
||||
>
|
||||
空闲
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="stove"
|
||||
:class="{ 'cooking': customerC.status === 'cooking', 'done': customerC.status === 'done' }"
|
||||
>
|
||||
<div class="stove-label">灶位 3</div>
|
||||
<div class="stove-label">
|
||||
灶位 3
|
||||
</div>
|
||||
<div class="stove-content">
|
||||
<div v-if="customerC.status === 'cooking'" class="cooking-text">烤鱼 {{ customerC.time }}s</div>
|
||||
<div v-if="customerC.status === 'done'" class="done-text">✅ 完成</div>
|
||||
<div v-if="customerC.status === 'waiting'" class="waiting-text">空闲</div>
|
||||
<div
|
||||
v-if="customerC.status === 'cooking'"
|
||||
class="cooking-text"
|
||||
>
|
||||
烤鱼 {{ customerC.time }}s
|
||||
</div>
|
||||
<div
|
||||
v-if="customerC.status === 'done'"
|
||||
class="done-text"
|
||||
>
|
||||
✅ 完成
|
||||
</div>
|
||||
<div
|
||||
v-if="customerC.status === 'waiting'"
|
||||
class="waiting-text"
|
||||
>
|
||||
空闲
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,51 +162,106 @@ const processCustomer = async (customer, realTime) => {
|
||||
<div class="customers">
|
||||
<h4>顾客</h4>
|
||||
<div class="customer-list">
|
||||
<div class="customer" :class="{ 'served': customerA.status === 'done' }">
|
||||
<div class="customer-avatar">👤</div>
|
||||
<div class="customer-info">
|
||||
<div class="customer-name">顾客 A</div>
|
||||
<div class="customer-order">煮面 ({{ customerA.time }}秒)</div>
|
||||
<div
|
||||
class="customer"
|
||||
:class="{ 'served': customerA.status === 'done' }"
|
||||
>
|
||||
<div class="customer-avatar">
|
||||
👤
|
||||
</div>
|
||||
<div class="customer-info">
|
||||
<div class="customer-name">
|
||||
顾客 A
|
||||
</div>
|
||||
<div class="customer-order">
|
||||
煮面 ({{ customerA.time }}秒)
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="customerA.status === 'done'"
|
||||
class="check-mark"
|
||||
>
|
||||
✅
|
||||
</div>
|
||||
<div v-if="customerA.status === 'done'" class="check-mark">✅</div>
|
||||
</div>
|
||||
<div class="customer" :class="{ 'served': customerB.status === 'done' }">
|
||||
<div class="customer-avatar">👤</div>
|
||||
<div class="customer-info">
|
||||
<div class="customer-name">顾客 B</div>
|
||||
<div class="customer-order">炒饭 ({{ customerB.time }}秒)</div>
|
||||
<div
|
||||
class="customer"
|
||||
:class="{ 'served': customerB.status === 'done' }"
|
||||
>
|
||||
<div class="customer-avatar">
|
||||
👤
|
||||
</div>
|
||||
<div class="customer-info">
|
||||
<div class="customer-name">
|
||||
顾客 B
|
||||
</div>
|
||||
<div class="customer-order">
|
||||
炒饭 ({{ customerB.time }}秒)
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="customerB.status === 'done'"
|
||||
class="check-mark"
|
||||
>
|
||||
✅
|
||||
</div>
|
||||
<div v-if="customerB.status === 'done'" class="check-mark">✅</div>
|
||||
</div>
|
||||
<div class="customer" :class="{ 'served': customerC.status === 'done' }">
|
||||
<div class="customer-avatar">👤</div>
|
||||
<div class="customer-info">
|
||||
<div class="customer-name">顾客 C</div>
|
||||
<div class="customer-order">烤鱼 ({{ customerC.time }}秒)</div>
|
||||
<div
|
||||
class="customer"
|
||||
:class="{ 'served': customerC.status === 'done' }"
|
||||
>
|
||||
<div class="customer-avatar">
|
||||
👤
|
||||
</div>
|
||||
<div class="customer-info">
|
||||
<div class="customer-name">
|
||||
顾客 C
|
||||
</div>
|
||||
<div class="customer-order">
|
||||
烤鱼 ({{ customerC.time }}秒)
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="customerC.status === 'done'"
|
||||
class="check-mark"
|
||||
>
|
||||
✅
|
||||
</div>
|
||||
<div v-if="customerC.status === 'done'" class="check-mark">✅</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button @click="start" :disabled="isRunning" class="btn-start">
|
||||
<button
|
||||
:disabled="isRunning"
|
||||
class="btn-start"
|
||||
@click="start"
|
||||
>
|
||||
{{ isRunning ? '执行中...' : '开始' }}
|
||||
</button>
|
||||
<button @click="reset" :disabled="isRunning" class="btn-reset">
|
||||
<button
|
||||
:disabled="isRunning"
|
||||
class="btn-reset"
|
||||
@click="reset"
|
||||
>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="comparison" v-if="!isRunning && (customerA.status === 'done' || customerB.status === 'done')">
|
||||
<div
|
||||
v-if="!isRunning && (customerA.status === 'done' || customerB.status === 'done')"
|
||||
class="comparison"
|
||||
>
|
||||
<div class="comparison-item">
|
||||
<strong>同步模式:</strong> 10 秒(依次执行)
|
||||
</div>
|
||||
<div class="comparison-item">
|
||||
<strong>异步模式:</strong> 约 5 秒(同时执行)
|
||||
</div>
|
||||
<div class="tip">JavaScript 用的就是异步模式——遇到耗时操作(如网络请求),不会傻等,而是先去做别的事。</div>
|
||||
<div class="tip">
|
||||
JavaScript 用的就是异步模式——遇到耗时操作(如网络请求),不会傻等,而是先去做别的事。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="code-display">
|
||||
|
||||
@@ -16,82 +16,158 @@
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
:key="tab.id"
|
||||
@click="activeTab = tab.id"
|
||||
class="tab-btn"
|
||||
:class="{ active: activeTab === tab.id }"
|
||||
@click="activeTab = tab.id"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 函数基础 -->
|
||||
<div v-if="activeTab === 'basic'" class="tab-content">
|
||||
<div
|
||||
v-if="activeTab === 'basic'"
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="function-showcase">
|
||||
<div class="code-panel">
|
||||
<div class="code-title">函数声明方式</div>
|
||||
<div class="code-title">
|
||||
函数声明方式
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line comment">// 1. 函数声明</div>
|
||||
<div class="code-line">function greet(name) {</div>
|
||||
<div class="code-line indent">return "Hello " + name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 2. 函数表达式</div>
|
||||
<div class="code-line">const greet = function(name) {</div>
|
||||
<div class="code-line indent">return "Hello " + name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 3. 箭头函数 (ES6)</div>
|
||||
<div class="code-line">const greet = (name) => {</div>
|
||||
<div class="code-line indent">return "Hello " + name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 简化版(单行可省略 return)</div>
|
||||
<div class="code-line">const greet = name => "Hello " + name</div>
|
||||
<div class="code-line comment">
|
||||
// 1. 函数声明
|
||||
</div>
|
||||
<div class="code-line">
|
||||
function greet(name) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return "Hello " + name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 2. 函数表达式
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const greet = function(name) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return "Hello " + name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 3. 箭头函数 (ES6)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const greet = (name) => {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return "Hello " + name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 简化版(单行可省略 return)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const greet = name => "Hello " + name
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="playground">
|
||||
<div class="playground-title">试试调用函数</div>
|
||||
<div class="playground-title">
|
||||
试试调用函数
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input v-model="functionName" placeholder="输入你的名字" />
|
||||
<button @click="callFunction">调用</button>
|
||||
<input
|
||||
v-model="functionName"
|
||||
placeholder="输入你的名字"
|
||||
>
|
||||
<button @click="callFunction">
|
||||
调用
|
||||
</button>
|
||||
</div>
|
||||
<div class="output">
|
||||
<span v-if="functionResult" class="result">{{ functionResult }}</span>
|
||||
<span v-else class="placeholder">点击"调用"按钮看结果...</span>
|
||||
<span
|
||||
v-if="functionResult"
|
||||
class="result"
|
||||
>{{ functionResult }}</span>
|
||||
<span
|
||||
v-else
|
||||
class="placeholder"
|
||||
>点击"调用"按钮看结果...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 闭包演示 -->
|
||||
<div v-else-if="activeTab === 'closure'" class="tab-content">
|
||||
<div
|
||||
v-else-if="activeTab === 'closure'"
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="closure-visual">
|
||||
<div class="scenario-selector">
|
||||
<button @click="closureScenario = 'counter'" :class="{ active: closureScenario === 'counter' }">
|
||||
<button
|
||||
:class="{ active: closureScenario === 'counter' }"
|
||||
@click="closureScenario = 'counter'"
|
||||
>
|
||||
计数器
|
||||
</button>
|
||||
<button @click="closureScenario = 'config'" :class="{ active: closureScenario === 'config' }">
|
||||
<button
|
||||
:class="{ active: closureScenario === 'config' }"
|
||||
@click="closureScenario = 'config'"
|
||||
>
|
||||
配置器
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="closureScenario === 'counter'" class="counter-demo">
|
||||
<div
|
||||
v-if="closureScenario === 'counter'"
|
||||
class="counter-demo"
|
||||
>
|
||||
<div class="code-panel small">
|
||||
<div class="code-line">function createCounter() {</div>
|
||||
<div class="code-line indent">let count = 0 <span class="comment">// 私有变量</span></div>
|
||||
<div class="code-line indent">return function() {</div>
|
||||
<div class="code-line indent indent">count++</div>
|
||||
<div class="code-line indent indent">return count</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">const counter = createCounter()</div>
|
||||
<div class="code-line">
|
||||
function createCounter() {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
let count = 0 <span class="comment">// 私有变量</span>
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return function() {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
count++
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
return count
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
const counter = createCounter()
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="closure-animation">
|
||||
<div class="closure-box">
|
||||
<div class="box-title">闭包环境</div>
|
||||
<div class="box-title">
|
||||
闭包环境
|
||||
</div>
|
||||
<div class="closure-var">
|
||||
<span class="var-label">count = </span>
|
||||
<span class="var-value">{{ counterValue }}</span>
|
||||
@@ -99,7 +175,10 @@
|
||||
</div>
|
||||
|
||||
<div class="controls-area">
|
||||
<button @click="incrementCounter" class="action-btn primary">
|
||||
<button
|
||||
class="action-btn primary"
|
||||
@click="incrementCounter"
|
||||
>
|
||||
调用 counter()
|
||||
</button>
|
||||
</div>
|
||||
@@ -116,36 +195,78 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="config-demo">
|
||||
<div
|
||||
v-else
|
||||
class="config-demo"
|
||||
>
|
||||
<div class="code-panel small">
|
||||
<div class="code-line">function makeMultiplier(times) {</div>
|
||||
<div class="code-line indent">return function(n) {</div>
|
||||
<div class="code-line indent indent">return n * times</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">const double = makeMultiplier(2)</div>
|
||||
<div class="code-line">const triple = makeMultiplier(3)</div>
|
||||
<div class="code-line">
|
||||
function makeMultiplier(times) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return function(n) {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
return n * times
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
const double = makeMultiplier(2)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const triple = makeMultiplier(3)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="multiplier-playground">
|
||||
<div class="function-list">
|
||||
<div class="func-item" @click="activeMultiplier = 'double'" :class="{ active: activeMultiplier === 'double' }">
|
||||
<div class="func-name">double = makeMultiplier(2)</div>
|
||||
<div class="func-desc">闭包捕获 times = 2</div>
|
||||
<div
|
||||
class="func-item"
|
||||
:class="{ active: activeMultiplier === 'double' }"
|
||||
@click="activeMultiplier = 'double'"
|
||||
>
|
||||
<div class="func-name">
|
||||
double = makeMultiplier(2)
|
||||
</div>
|
||||
<div class="func-desc">
|
||||
闭包捕获 times = 2
|
||||
</div>
|
||||
</div>
|
||||
<div class="func-item" @click="activeMultiplier = 'triple'" :class="{ active: activeMultiplier === 'triple' }">
|
||||
<div class="func-name">triple = makeMultiplier(3)</div>
|
||||
<div class="func-desc">闭包捕获 times = 3</div>
|
||||
<div
|
||||
class="func-item"
|
||||
:class="{ active: activeMultiplier === 'triple' }"
|
||||
@click="activeMultiplier = 'triple'"
|
||||
>
|
||||
<div class="func-name">
|
||||
triple = makeMultiplier(3)
|
||||
</div>
|
||||
<div class="func-desc">
|
||||
闭包捕获 times = 3
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="multiplier-input">
|
||||
<input v-model.number="multiplyNumber" type="number" placeholder="输入数字" />
|
||||
<button @click="doMultiply">计算</button>
|
||||
<input
|
||||
v-model.number="multiplyNumber"
|
||||
type="number"
|
||||
placeholder="输入数字"
|
||||
>
|
||||
<button @click="doMultiply">
|
||||
计算
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="multiplyResult" class="multiply-result">
|
||||
<div
|
||||
v-if="multiplyResult"
|
||||
class="multiply-result"
|
||||
>
|
||||
<span class="result-equation">{{ multiplyResult }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -154,23 +275,32 @@
|
||||
</div>
|
||||
|
||||
<!-- 作用域链 -->
|
||||
<div v-else class="tab-content">
|
||||
<div
|
||||
v-else
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="scope-chain-demo">
|
||||
<div class="nested-visual">
|
||||
<div class="scope-level global">
|
||||
<div class="level-title">全局作用域</div>
|
||||
<div class="level-title">
|
||||
全局作用域
|
||||
</div>
|
||||
<div class="level-vars">
|
||||
<span class="var-tag">globalVar = "全局"</span>
|
||||
</div>
|
||||
|
||||
<div class="scope-level outer">
|
||||
<div class="level-title">外层函数作用域</div>
|
||||
<div class="level-title">
|
||||
外层函数作用域
|
||||
</div>
|
||||
<div class="level-vars">
|
||||
<span class="var-tag">outerVar = "外层"</span>
|
||||
</div>
|
||||
|
||||
<div class="scope-level inner">
|
||||
<div class="level-title">内层函数作用域</div>
|
||||
<div class="level-title">
|
||||
内层函数作用域
|
||||
</div>
|
||||
<div class="level-vars">
|
||||
<span class="var-tag">innerVar = "内层"</span>
|
||||
</div>
|
||||
@@ -180,11 +310,21 @@
|
||||
</div>
|
||||
|
||||
<div class="lookup-demo">
|
||||
<div class="lookup-title">🔍 变量查找过程(作用域链)</div>
|
||||
<div class="lookup-title">
|
||||
🔍 变量查找过程(作用域链)
|
||||
</div>
|
||||
<div class="lookup-steps">
|
||||
<div class="lookup-step" v-for="(step, i) in lookupSteps" :key="i">
|
||||
<div class="step-num">{{ i + 1 }}</div>
|
||||
<div class="step-content">{{ step }}</div>
|
||||
<div
|
||||
v-for="(step, i) in lookupSteps"
|
||||
:key="i"
|
||||
class="lookup-step"
|
||||
>
|
||||
<div class="step-num">
|
||||
{{ i + 1 }}
|
||||
</div>
|
||||
<div class="step-content">
|
||||
{{ step }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -34,16 +34,23 @@ const removeItem = () => {
|
||||
<div class="webpage-preview">
|
||||
<div class="browser-bar">
|
||||
<div class="dots">
|
||||
<span class="dot red"></span>
|
||||
<span class="dot yellow"></span>
|
||||
<span class="dot green"></span>
|
||||
<span class="dot red" />
|
||||
<span class="dot yellow" />
|
||||
<span class="dot green" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="webpage-content">
|
||||
<h1>{{ title }}</h1>
|
||||
<p :style="{ color: paragraphColor }">欢迎光临</p>
|
||||
<p :style="{ color: paragraphColor }">
|
||||
欢迎光临
|
||||
</p>
|
||||
<ul>
|
||||
<li v-for="(item, index) in items" :key="index">{{ item }}</li>
|
||||
<li
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,18 +63,28 @@ const removeItem = () => {
|
||||
<div class="tree-node">
|
||||
<span class="tag"><body></span>
|
||||
<div class="tree-children">
|
||||
<div class="tree-node" :class="{ 'active': title === 'Hello World!' }">
|
||||
<div
|
||||
class="tree-node"
|
||||
:class="{ 'active': title === 'Hello World!' }"
|
||||
>
|
||||
<span class="tag"><h1></span>
|
||||
<span class="text">{{ title }}</span>
|
||||
</div>
|
||||
<div class="tree-node" :class="{ 'active': paragraphColor === 'red' }">
|
||||
<div
|
||||
class="tree-node"
|
||||
:class="{ 'active': paragraphColor === 'red' }"
|
||||
>
|
||||
<span class="tag"><p></span>
|
||||
<span class="text">欢迎光临</span>
|
||||
</div>
|
||||
<div class="tree-node">
|
||||
<span class="tag"><ul></span>
|
||||
<div class="tree-children">
|
||||
<div class="tree-node" v-for="(item, index) in items" :key="index">
|
||||
<div
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
class="tree-node"
|
||||
>
|
||||
<span class="tag"><li></span>
|
||||
<span class="text">{{ item }}</span>
|
||||
</div>
|
||||
@@ -81,10 +98,30 @@ const removeItem = () => {
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button @click="modifyTitle" class="btn-primary">修改标题</button>
|
||||
<button @click="addItem" class="btn-secondary">添加列表项</button>
|
||||
<button @click="changeColor" class="btn-secondary">改变段落颜色</button>
|
||||
<button @click="removeItem" class="btn-danger">删除列表项</button>
|
||||
<button
|
||||
class="btn-primary"
|
||||
@click="modifyTitle"
|
||||
>
|
||||
修改标题
|
||||
</button>
|
||||
<button
|
||||
class="btn-secondary"
|
||||
@click="addItem"
|
||||
>
|
||||
添加列表项
|
||||
</button>
|
||||
<button
|
||||
class="btn-secondary"
|
||||
@click="changeColor"
|
||||
>
|
||||
改变段落颜色
|
||||
</button>
|
||||
<button
|
||||
class="btn-danger"
|
||||
@click="removeItem"
|
||||
>
|
||||
删除列表项
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="code-display">
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
:key="tab.id"
|
||||
@click="activeTab = tab.id"
|
||||
class="tab-btn"
|
||||
:class="{ active: activeTab === tab.id }"
|
||||
@click="activeTab = tab.id"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
@@ -26,24 +26,40 @@
|
||||
|
||||
<div class="content-area">
|
||||
<!-- 原始类型 -->
|
||||
<div v-if="activeTab === 'primitive'" class="primitive-types">
|
||||
<div
|
||||
v-if="activeTab === 'primitive'"
|
||||
class="primitive-types"
|
||||
>
|
||||
<div class="type-grid">
|
||||
<div
|
||||
v-for="type in primitiveTypes"
|
||||
:key="type.name"
|
||||
class="type-card"
|
||||
@click="selectedType = type"
|
||||
:class="{ selected: selectedType?.name === type.name }"
|
||||
@click="selectedType = type"
|
||||
>
|
||||
<div class="type-icon">{{ type.icon }}</div>
|
||||
<div class="type-name">{{ type.name }}</div>
|
||||
<div class="type-example">{{ type.example }}</div>
|
||||
<div class="type-icon">
|
||||
{{ type.icon }}
|
||||
</div>
|
||||
<div class="type-name">
|
||||
{{ type.name }}
|
||||
</div>
|
||||
<div class="type-example">
|
||||
{{ type.example }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedType" class="type-detail">
|
||||
<div class="detail-title">📝 {{ selectedType.name }} 详细说明</div>
|
||||
<div class="detail-desc">{{ selectedType.description }}</div>
|
||||
<div
|
||||
v-if="selectedType"
|
||||
class="type-detail"
|
||||
>
|
||||
<div class="detail-title">
|
||||
📝 {{ selectedType.name }} 详细说明
|
||||
</div>
|
||||
<div class="detail-desc">
|
||||
{{ selectedType.description }}
|
||||
</div>
|
||||
<div class="detail-note">
|
||||
<strong>💡 关键特性:</strong>{{ selectedType.note }}
|
||||
</div>
|
||||
@@ -51,66 +67,130 @@
|
||||
</div>
|
||||
|
||||
<!-- 引用类型 -->
|
||||
<div v-else-if="activeTab === 'reference'" class="reference-types">
|
||||
<div
|
||||
v-else-if="activeTab === 'reference'"
|
||||
class="reference-types"
|
||||
>
|
||||
<div class="comparison-box">
|
||||
<div class="compare-side">
|
||||
<div class="side-title">原始类型赋值</div>
|
||||
<div class="side-title">
|
||||
原始类型赋值
|
||||
</div>
|
||||
<div class="code-example">
|
||||
<div class="code-line">let a = 10</div>
|
||||
<div class="code-line">let b = a</div>
|
||||
<div class="code-line">b = 20</div>
|
||||
<div class="code-line result">// a = 10 (不变)</div>
|
||||
<div class="code-line">
|
||||
let a = 10
|
||||
</div>
|
||||
<div class="code-line">
|
||||
let b = a
|
||||
</div>
|
||||
<div class="code-line">
|
||||
b = 20
|
||||
</div>
|
||||
<div class="code-line result">
|
||||
// a = 10 (不变)
|
||||
</div>
|
||||
</div>
|
||||
<div class="visual-box">
|
||||
<div class="value-box">a = 10</div>
|
||||
<div class="arrow">复制</div>
|
||||
<div class="value-box">b = 20</div>
|
||||
<div class="value-box">
|
||||
a = 10
|
||||
</div>
|
||||
<div class="arrow">
|
||||
复制
|
||||
</div>
|
||||
<div class="value-box">
|
||||
b = 20
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="compare-side">
|
||||
<div class="side-title">引用类型赋值</div>
|
||||
<div class="side-title">
|
||||
引用类型赋值
|
||||
</div>
|
||||
<div class="code-example">
|
||||
<div class="code-line">let obj1 = {x: 10}</div>
|
||||
<div class="code-line">let obj2 = obj1</div>
|
||||
<div class="code-line">obj2.x = 20</div>
|
||||
<div class="code-line result">// obj1.x = 20 (变了!)</div>
|
||||
<div class="code-line">
|
||||
let obj1 = {x: 10}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
let obj2 = obj1
|
||||
</div>
|
||||
<div class="code-line">
|
||||
obj2.x = 20
|
||||
</div>
|
||||
<div class="code-line result">
|
||||
// obj1.x = 20 (变了!)
|
||||
</div>
|
||||
</div>
|
||||
<div class="visual-box ref-visual">
|
||||
<div class="ref-boxes">
|
||||
<div class="ref-var-box">
|
||||
<div class="ref-var-name">obj1</div>
|
||||
<div class="ref-var-arrow">→</div>
|
||||
<div class="ref-var-name">
|
||||
obj1
|
||||
</div>
|
||||
<div class="ref-var-arrow">
|
||||
→
|
||||
</div>
|
||||
</div>
|
||||
<div class="ref-var-box">
|
||||
<div class="ref-var-name">obj2</div>
|
||||
<div class="ref-var-arrow">→</div>
|
||||
<div class="ref-var-name">
|
||||
obj2
|
||||
</div>
|
||||
<div class="ref-var-arrow">
|
||||
→
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="arrow down-arrow">指向同一位置</div>
|
||||
<div class="memory-box">{x: 20}</div>
|
||||
<div class="arrow down-arrow">
|
||||
指向同一位置
|
||||
</div>
|
||||
<div class="memory-box">
|
||||
{x: 20}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ref-types-list">
|
||||
<div class="ref-type-item" v-for="type in referenceTypes" :key="type.name">
|
||||
<div class="ref-icon">{{ type.icon }}</div>
|
||||
<div
|
||||
v-for="type in referenceTypes"
|
||||
:key="type.name"
|
||||
class="ref-type-item"
|
||||
>
|
||||
<div class="ref-icon">
|
||||
{{ type.icon }}
|
||||
</div>
|
||||
<div class="ref-info">
|
||||
<div class="ref-name">{{ type.name }}</div>
|
||||
<div class="ref-desc">{{ type.description }}</div>
|
||||
<div class="ref-name">
|
||||
{{ type.name }}
|
||||
</div>
|
||||
<div class="ref-desc">
|
||||
{{ type.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 类型转换 -->
|
||||
<div v-else class="type-conversion">
|
||||
<div
|
||||
v-else
|
||||
class="type-conversion"
|
||||
>
|
||||
<div class="conversion-playground">
|
||||
<div class="input-section">
|
||||
<label>输入一个值:</label>
|
||||
<input v-model="inputValue" type="text" placeholder="试试输入 '123' 或 'hello'" @keyup.enter="convertType" />
|
||||
<button @click="convertType" class="convert-btn">转换</button>
|
||||
<input
|
||||
v-model="inputValue"
|
||||
type="text"
|
||||
placeholder="试试输入 '123' 或 'hello'"
|
||||
@keyup.enter="convertType"
|
||||
>
|
||||
<button
|
||||
class="convert-btn"
|
||||
@click="convertType"
|
||||
>
|
||||
转换
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="results-section">
|
||||
@@ -120,7 +200,10 @@
|
||||
</div>
|
||||
<div class="result-row">
|
||||
<span class="result-label">Number():</span>
|
||||
<span class="result-value" :class="{ error: conversionResults.number === 'NaN' }">
|
||||
<span
|
||||
class="result-value"
|
||||
:class="{ error: conversionResults.number === 'NaN' }"
|
||||
>
|
||||
{{ conversionResults.number }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -131,11 +214,19 @@
|
||||
</div>
|
||||
|
||||
<div class="falsy-values">
|
||||
<div class="falsy-title">⚠️ 转成 false 的值(falsy values):</div>
|
||||
<div class="falsy-list">
|
||||
<span v-for="val in falsyValues" :key="val" class="falsy-item">{{ val }}</span>
|
||||
<div class="falsy-title">
|
||||
⚠️ 转成 false 的值(falsy values):
|
||||
</div>
|
||||
<div class="falsy-list">
|
||||
<span
|
||||
v-for="val in falsyValues"
|
||||
:key="val"
|
||||
class="falsy-item"
|
||||
>{{ val }}</span>
|
||||
</div>
|
||||
<div class="falsy-note">
|
||||
其他所有值(包括空数组 []、空对象 {})都转成 true
|
||||
</div>
|
||||
<div class="falsy-note">其他所有值(包括空数组 []、空对象 {})都转成 true</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -41,11 +41,19 @@ const currentCode = ref(`const calculatePrice = (price, discount) => {
|
||||
<div class="input-group">
|
||||
<label>
|
||||
价格:
|
||||
<input v-model.number="price" type="number" min="0" :disabled="isRunning" />
|
||||
<input
|
||||
v-model.number="price"
|
||||
type="number"
|
||||
min="0"
|
||||
:disabled="isRunning"
|
||||
>
|
||||
</label>
|
||||
<label>
|
||||
折扣:
|
||||
<select v-model.number="discount" :disabled="isRunning">
|
||||
<select
|
||||
v-model.number="discount"
|
||||
:disabled="isRunning"
|
||||
>
|
||||
<option :value="0.8">8 折 (0.8)</option>
|
||||
<option :value="0.5">5 折 (0.5)</option>
|
||||
<option :value="0.7">7 折 (0.7)</option>
|
||||
@@ -58,7 +66,9 @@ const currentCode = ref(`const calculatePrice = (price, discount) => {
|
||||
<div class="pipeline-section machine-section">
|
||||
<h4>函数</h4>
|
||||
<div class="machine">
|
||||
<div class="machine-label">calculatePrice</div>
|
||||
<div class="machine-label">
|
||||
calculatePrice
|
||||
</div>
|
||||
<div class="machine-code">
|
||||
<pre v-if="functionType === 'declaration'"><code>return price * discount</code></pre>
|
||||
<pre v-else-if="functionType === 'expression'"><code>return price * discount</code></pre>
|
||||
@@ -70,28 +80,50 @@ const currentCode = ref(`const calculatePrice = (price, discount) => {
|
||||
<button
|
||||
v-for="type in functionTypes"
|
||||
:key="type.value"
|
||||
@click="functionType = type.value"
|
||||
:class="{ active: functionType === type.value }"
|
||||
class="type-btn"
|
||||
@click="functionType = type.value"
|
||||
>
|
||||
{{ type.label }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="tip" v-if="functionType !== 'arrow'">✏️ 写法不同,但做的事一模一样</div>
|
||||
<div
|
||||
v-if="functionType !== 'arrow'"
|
||||
class="tip"
|
||||
>
|
||||
✏️ 写法不同,但做的事一模一样
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 输出区 -->
|
||||
<div class="pipeline-section output-section">
|
||||
<h4>返回值(输出)</h4>
|
||||
<div class="output-display" :class="{ 'processing': isRunning }">
|
||||
<div v-if="result === null" class="placeholder">?</div>
|
||||
<div v-else class="result">¥{{ result.toFixed(2) }}</div>
|
||||
<div
|
||||
class="output-display"
|
||||
:class="{ 'processing': isRunning }"
|
||||
>
|
||||
<div
|
||||
v-if="result === null"
|
||||
class="placeholder"
|
||||
>
|
||||
?
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="result"
|
||||
>
|
||||
¥{{ result.toFixed(2) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button @click="execute" :disabled="isRunning" class="btn-execute">
|
||||
<button
|
||||
:disabled="isRunning"
|
||||
class="btn-execute"
|
||||
@click="execute"
|
||||
>
|
||||
{{ isRunning ? '处理中...' : '执行 ▶' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -91,9 +91,18 @@ const stop = () => {
|
||||
'processed': currentStep > index
|
||||
}"
|
||||
>
|
||||
<div class="item-index">{{ item.id }}</div>
|
||||
<div class="item-code">{{ item.code }}</div>
|
||||
<div v-if="currentStep === index" class="executing">执行中</div>
|
||||
<div class="item-index">
|
||||
{{ item.id }}
|
||||
</div>
|
||||
<div class="item-code">
|
||||
{{ item.code }}
|
||||
</div>
|
||||
<div
|
||||
v-if="currentStep === index"
|
||||
class="executing"
|
||||
>
|
||||
执行中
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,11 +111,16 @@ const stop = () => {
|
||||
<div class="worker-section">
|
||||
<h4>工位(单线程)</h4>
|
||||
<div class="worker">
|
||||
<div class="worker-emoji">👨💻</div>
|
||||
<div class="worker-emoji">
|
||||
👨💻
|
||||
</div>
|
||||
<div class="worker-status">
|
||||
{{ currentStep < steps.length ? '正在执行' : '执行完成' }}
|
||||
</div>
|
||||
<div v-if="currentStep < steps.length" class="current-task">
|
||||
<div
|
||||
v-if="currentStep < steps.length"
|
||||
class="current-task"
|
||||
>
|
||||
{{ steps[currentStep]?.description }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,12 +136,17 @@ const stop = () => {
|
||||
class="task-item"
|
||||
:class="{ 'ready': task.status === 'ready' }"
|
||||
>
|
||||
<div class="task-code">{{ task.code }}</div>
|
||||
<div class="task-code">
|
||||
{{ task.code }}
|
||||
</div>
|
||||
<div class="task-status">
|
||||
{{ task.status === 'ready' ? '✅ 就绪' : '⏳ 等待中...' }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="taskQueue.length === 0" class="empty-queue">
|
||||
<div
|
||||
v-if="taskQueue.length === 0"
|
||||
class="empty-queue"
|
||||
>
|
||||
暂无待办任务
|
||||
</div>
|
||||
</div>
|
||||
@@ -138,7 +157,12 @@ const stop = () => {
|
||||
<div class="output-section">
|
||||
<h4>输出日志</h4>
|
||||
<div class="output-log">
|
||||
<div v-if="outputLog.length === 0" class="empty-log">等待输出...</div>
|
||||
<div
|
||||
v-if="outputLog.length === 0"
|
||||
class="empty-log"
|
||||
>
|
||||
等待输出...
|
||||
</div>
|
||||
<div
|
||||
v-for="(log, index) in outputLog"
|
||||
:key="index"
|
||||
@@ -152,16 +176,31 @@ const stop = () => {
|
||||
|
||||
<!-- 控制按钮 -->
|
||||
<div class="controls">
|
||||
<button @click="play" :disabled="isPlaying || currentStep >= steps.length" class="btn-play">
|
||||
<button
|
||||
:disabled="isPlaying || currentStep >= steps.length"
|
||||
class="btn-play"
|
||||
@click="play"
|
||||
>
|
||||
{{ isPlaying ? '执行中...' : '▶ 自动播放' }}
|
||||
</button>
|
||||
<button @click="nextStep" :disabled="isPlaying || currentStep >= steps.length" class="btn-step">
|
||||
<button
|
||||
:disabled="isPlaying || currentStep >= steps.length"
|
||||
class="btn-step"
|
||||
@click="nextStep"
|
||||
>
|
||||
⏭ 单步执行
|
||||
</button>
|
||||
<button @click="stop" :disabled="!isPlaying" class="btn-stop">
|
||||
<button
|
||||
:disabled="!isPlaying"
|
||||
class="btn-stop"
|
||||
@click="stop"
|
||||
>
|
||||
⏸ 停止
|
||||
</button>
|
||||
<button @click="reset" class="btn-reset">
|
||||
<button
|
||||
class="btn-reset"
|
||||
@click="reset"
|
||||
>
|
||||
🔄 重置
|
||||
</button>
|
||||
</div>
|
||||
@@ -170,7 +209,9 @@ const stop = () => {
|
||||
<div class="explanation">
|
||||
<p><strong>执行顺序:</strong>{{ outputLog.map(l => l.output).join(', ') || '还未开始' }}</p>
|
||||
<p><strong>代码书写顺序:</strong>1, 2, 3, 4, 5</p>
|
||||
<p class="highlight">代码从上到下写的,但执行顺序不一定从上到下——因为异步操作会被"推迟"到当前代码执行完之后。</p>
|
||||
<p class="highlight">
|
||||
代码从上到下写的,但执行顺序不一定从上到下——因为异步操作会被"推迟"到当前代码执行完之后。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -16,61 +16,126 @@
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
:key="tab.id"
|
||||
@click="activeTab = tab.id"
|
||||
class="tab-btn"
|
||||
:class="{ active: activeTab === tab.id }"
|
||||
@click="activeTab = tab.id"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 原型基础 -->
|
||||
<div v-if="activeTab === 'basic'" class="tab-content">
|
||||
<div
|
||||
v-if="activeTab === 'basic'"
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="concept-explanation">
|
||||
<div class="code-panel">
|
||||
<div class="code-title">创建对象的方式</div>
|
||||
<div class="code-title">
|
||||
创建对象的方式
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line comment">// 方式 1:对象字面量</div>
|
||||
<div class="code-line">const obj1 = { name: "对象1" }</div>
|
||||
<div class="code-line">obj1.__proto__ === Object.prototype <span class="comment">// true</span></div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 方式 2:构造函数</div>
|
||||
<div class="code-line">function Person(name) {</div>
|
||||
<div class="code-line indent">this.name = name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line">const p = new Person("张三")</div>
|
||||
<div class="code-line">p.__proto__ === Person.prototype <span class="comment">// true</span></div>
|
||||
<div class="code-line comment">
|
||||
// 方式 1:对象字面量
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const obj1 = { name: "对象1" }
|
||||
</div>
|
||||
<div class="code-line">
|
||||
obj1.__proto__ === Object.prototype <span class="comment">// true</span>
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 方式 2:构造函数
|
||||
</div>
|
||||
<div class="code-line">
|
||||
function Person(name) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
this.name = name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const p = new Person("张三")
|
||||
</div>
|
||||
<div class="code-line">
|
||||
p.__proto__ === Person.prototype <span class="comment">// true</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="prototype-visual">
|
||||
<div class="prototype-chain">
|
||||
<div class="chain-node" :class="{ active: chainLevel >= 0 }" @click="chainLevel = 0">
|
||||
<div class="node-title">对象实例 (p)</div>
|
||||
<div
|
||||
class="chain-node"
|
||||
:class="{ active: chainLevel >= 0 }"
|
||||
@click="chainLevel = 0"
|
||||
>
|
||||
<div class="node-title">
|
||||
对象实例 (p)
|
||||
</div>
|
||||
<div class="node-content">
|
||||
<div class="property">name: "张三"</div>
|
||||
<div class="proto-link">__proto__ →</div>
|
||||
<div class="property">
|
||||
name: "张三"
|
||||
</div>
|
||||
<div class="proto-link">
|
||||
__proto__ →
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chain-arrow" v-if="chainLevel >= 0">↓ 查找</div>
|
||||
<div
|
||||
v-if="chainLevel >= 0"
|
||||
class="chain-arrow"
|
||||
>
|
||||
↓ 查找
|
||||
</div>
|
||||
|
||||
<div class="chain-node constructor" :class="{ active: chainLevel >= 1 }" @click="chainLevel = 1">
|
||||
<div class="node-title">Person.prototype</div>
|
||||
<div
|
||||
class="chain-node constructor"
|
||||
:class="{ active: chainLevel >= 1 }"
|
||||
@click="chainLevel = 1"
|
||||
>
|
||||
<div class="node-title">
|
||||
Person.prototype
|
||||
</div>
|
||||
<div class="node-content">
|
||||
<div class="method">constructor: Person</div>
|
||||
<div class="proto-link">__proto__ →</div>
|
||||
<div class="method">
|
||||
constructor: Person
|
||||
</div>
|
||||
<div class="proto-link">
|
||||
__proto__ →
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chain-arrow" v-if="chainLevel >= 1">↓ 查找</div>
|
||||
<div
|
||||
v-if="chainLevel >= 1"
|
||||
class="chain-arrow"
|
||||
>
|
||||
↓ 查找
|
||||
</div>
|
||||
|
||||
<div class="chain-node object" :class="{ active: chainLevel >= 2 }" @click="chainLevel = 2">
|
||||
<div class="node-title">Object.prototype</div>
|
||||
<div
|
||||
class="chain-node object"
|
||||
:class="{ active: chainLevel >= 2 }"
|
||||
@click="chainLevel = 2"
|
||||
>
|
||||
<div class="node-title">
|
||||
Object.prototype
|
||||
</div>
|
||||
<div class="node-content">
|
||||
<div class="method">toString()</div>
|
||||
<div class="method">hasOwnProperty()</div>
|
||||
<div class="proto-link">__proto__ → null</div>
|
||||
<div class="method">
|
||||
toString()
|
||||
</div>
|
||||
<div class="method">
|
||||
hasOwnProperty()
|
||||
</div>
|
||||
<div class="proto-link">
|
||||
__proto__ → null
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,75 +159,149 @@
|
||||
</div>
|
||||
|
||||
<!-- 原型继承 -->
|
||||
<div v-else-if="activeTab === 'inheritance'" class="tab-content">
|
||||
<div
|
||||
v-else-if="activeTab === 'inheritance'"
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="inheritance-demo">
|
||||
<div class="inheritance-code">
|
||||
<div class="code-title">原型继承示例</div>
|
||||
<div class="code-title">
|
||||
原型继承示例
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line comment">// 父类构造函数</div>
|
||||
<div class="code-line">function Animal(name) {</div>
|
||||
<div class="code-line indent">this.name = name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">Animal.prototype.eat = function() {</div>
|
||||
<div class="code-line indent">return this.name + " 在吃东西"</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 子类构造函数</div>
|
||||
<div class="code-line">function Dog(name, breed) {</div>
|
||||
<div class="code-line indent">Animal.call(this, name) <span class="comment">// 继承属性</span></div>
|
||||
<div class="code-line indent">this.breed = breed</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 继承方法</div>
|
||||
<div class="code-line">Dog.prototype = Object.create(Animal.prototype)</div>
|
||||
<div class="code-line">Dog.prototype.constructor = Dog</div>
|
||||
<div class="code-line comment">
|
||||
// 父类构造函数
|
||||
</div>
|
||||
<div class="code-line">
|
||||
function Animal(name) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
this.name = name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
Animal.prototype.eat = function() {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return this.name + " 在吃东西"
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 子类构造函数
|
||||
</div>
|
||||
<div class="code-line">
|
||||
function Dog(name, breed) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
Animal.call(this, name) <span class="comment">// 继承属性</span>
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
this.breed = breed
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 继承方法
|
||||
</div>
|
||||
<div class="code-line">
|
||||
Dog.prototype = Object.create(Animal.prototype)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
Dog.prototype.constructor = Dog
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inheritance-visual">
|
||||
<div class="class-diagram">
|
||||
<div class="class-box parent">
|
||||
<div class="class-title">Animal (父类)</div>
|
||||
<div class="class-title">
|
||||
Animal (父类)
|
||||
</div>
|
||||
<div class="class-content">
|
||||
<div class="class-section">
|
||||
<div class="section-title">属性</div>
|
||||
<div class="section-item">name: String</div>
|
||||
<div class="section-title">
|
||||
属性
|
||||
</div>
|
||||
<div class="section-item">
|
||||
name: String
|
||||
</div>
|
||||
</div>
|
||||
<div class="class-section">
|
||||
<div class="section-title">方法 (prototype)</div>
|
||||
<div class="section-item">eat()</div>
|
||||
<div class="section-title">
|
||||
方法 (prototype)
|
||||
</div>
|
||||
<div class="section-item">
|
||||
eat()
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inherit-arrow">↓ 继承</div>
|
||||
<div class="inherit-arrow">
|
||||
↓ 继承
|
||||
</div>
|
||||
|
||||
<div class="class-box child">
|
||||
<div class="class-title">Dog (子类)</div>
|
||||
<div class="class-title">
|
||||
Dog (子类)
|
||||
</div>
|
||||
<div class="class-content">
|
||||
<div class="class-section">
|
||||
<div class="section-title">属性</div>
|
||||
<div class="section-item">name: String</div>
|
||||
<div class="section-item">breed: String</div>
|
||||
<div class="section-title">
|
||||
属性
|
||||
</div>
|
||||
<div class="section-item">
|
||||
name: String
|
||||
</div>
|
||||
<div class="section-item">
|
||||
breed: String
|
||||
</div>
|
||||
</div>
|
||||
<div class="class-section">
|
||||
<div class="section-title">方法 (prototype)</div>
|
||||
<div class="section-item">eat() <span class="inherited">[继承]</span></div>
|
||||
<div class="section-item">bark() <span class="own">[新增]</span></div>
|
||||
<div class="section-title">
|
||||
方法 (prototype)
|
||||
</div>
|
||||
<div class="section-item">
|
||||
eat() <span class="inherited">[继承]</span>
|
||||
</div>
|
||||
<div class="section-item">
|
||||
bark() <span class="own">[新增]</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inheritance-playground">
|
||||
<div class="playground-title">试试创建实例</div>
|
||||
<div class="input-group">
|
||||
<input v-model="dogName" placeholder="狗狗名字" />
|
||||
<input v-model="dogBreed" placeholder="品种" />
|
||||
<button @click="createDog">创建</button>
|
||||
<div class="playground-title">
|
||||
试试创建实例
|
||||
</div>
|
||||
<div v-if="dogInstance" class="instance-result">
|
||||
<div class="input-group">
|
||||
<input
|
||||
v-model="dogName"
|
||||
placeholder="狗狗名字"
|
||||
>
|
||||
<input
|
||||
v-model="dogBreed"
|
||||
placeholder="品种"
|
||||
>
|
||||
<button @click="createDog">
|
||||
创建
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
v-if="dogInstance"
|
||||
class="instance-result"
|
||||
>
|
||||
<div class="result-item">
|
||||
<span class="label">名字:</span>
|
||||
<span class="value">{{ dogInstance.name }}</span>
|
||||
@@ -173,8 +312,16 @@
|
||||
</div>
|
||||
<div class="result-item">
|
||||
<span class="label">调用 eat():</span>
|
||||
<button @click="callEat" class="action-btn">调用</button>
|
||||
<span v-if="eatResult" class="method-result">{{ eatResult }}</span>
|
||||
<button
|
||||
class="action-btn"
|
||||
@click="callEat"
|
||||
>
|
||||
调用
|
||||
</button>
|
||||
<span
|
||||
v-if="eatResult"
|
||||
class="method-result"
|
||||
>{{ eatResult }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -183,90 +330,185 @@
|
||||
</div>
|
||||
|
||||
<!-- class 语法 -->
|
||||
<div v-else class="tab-content">
|
||||
<div
|
||||
v-else
|
||||
class="tab-content"
|
||||
>
|
||||
<div class="class-syntax-demo">
|
||||
<div class="syntax-comparison">
|
||||
<div class="syntax-panel old">
|
||||
<div class="panel-title">ES5 构造函数</div>
|
||||
<div class="panel-title">
|
||||
ES5 构造函数
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">function Person(name) {</div>
|
||||
<div class="code-line indent">this.name = name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">Person.prototype.greet = function() {</div>
|
||||
<div class="code-line indent">return "你好,我是" + this.name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">const p = new Person("小明")</div>
|
||||
<div class="code-line">
|
||||
function Person(name) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
this.name = name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
Person.prototype.greet = function() {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return "你好,我是" + this.name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
const p = new Person("小明")
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="syntax-panel new">
|
||||
<div class="panel-title">ES6 class 语法</div>
|
||||
<div class="panel-title">
|
||||
ES6 class 语法
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">class Person {</div>
|
||||
<div class="code-line indent">constructor(name) {</div>
|
||||
<div class="code-line indent indent">this.name = name</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line indent">greet() {</div>
|
||||
<div class="code-line indent indent">return "你好,我是" + this.name</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">const p = new Person("小明")</div>
|
||||
<div class="code-line">
|
||||
class Person {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
constructor(name) {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
this.name = name
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line indent">
|
||||
greet() {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
return "你好,我是" + this.name
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
const p = new Person("小明")
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="class-features">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🎯</div>
|
||||
<div class="feature-title">更清晰的语法</div>
|
||||
<div class="feature-desc">class 语法让面向对象编程更直观,但本质还是基于原型</div>
|
||||
<div class="feature-icon">
|
||||
🎯
|
||||
</div>
|
||||
<div class="feature-title">
|
||||
更清晰的语法
|
||||
</div>
|
||||
<div class="feature-desc">
|
||||
class 语法让面向对象编程更直观,但本质还是基于原型
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">🔗</div>
|
||||
<div class="feature-title">继承更简单</div>
|
||||
<div class="feature-desc">使用 extends 关键字实现继承,代码更简洁</div>
|
||||
<div class="feature-icon">
|
||||
🔗
|
||||
</div>
|
||||
<div class="feature-title">
|
||||
继承更简单
|
||||
</div>
|
||||
<div class="feature-desc">
|
||||
使用 extends 关键字实现继承,代码更简洁
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon">⚠️</div>
|
||||
<div class="feature-title">注意</div>
|
||||
<div class="feature-desc">class 只是语法糖,底层仍然是原型链机制</div>
|
||||
<div class="feature-icon">
|
||||
⚠️
|
||||
</div>
|
||||
<div class="feature-title">
|
||||
注意
|
||||
</div>
|
||||
<div class="feature-desc">
|
||||
class 只是语法糖,底层仍然是原型链机制
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inheritance-example">
|
||||
<div class="code-title">class 继承示例</div>
|
||||
<div class="code-title">
|
||||
class 继承示例
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">class Animal {</div>
|
||||
<div class="code-line indent">constructor(name) {</div>
|
||||
<div class="code-line indent indent">this.name = name</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line indent">eat() {</div>
|
||||
<div class="code-line indent indent">return this.name + " 在吃东西"</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">class Dog extends Animal {</div>
|
||||
<div class="code-line indent">constructor(name, breed) {</div>
|
||||
<div class="code-line indent indent">super(name) <span class="comment">// 调用父类构造函数</span></div>
|
||||
<div class="code-line indent indent">this.breed = breed</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line indent">bark() {</div>
|
||||
<div class="code-line indent indent">return "汪汪!"</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line">
|
||||
class Animal {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
constructor(name) {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
this.name = name
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
eat() {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
return this.name + " 在吃东西"
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
class Dog extends Animal {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
constructor(name, breed) {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
super(name) <span class="comment">// 调用父类构造函数</span>
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
this.breed = breed
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
bark() {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
return "汪汪!"
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="key-points">
|
||||
<div class="point-title">🎯 核心要点</div>
|
||||
<div class="point-title">
|
||||
🎯 核心要点
|
||||
</div>
|
||||
<ul class="point-list">
|
||||
<li>每个对象都有 <code>__proto__</code> 属性,指向其构造函数的 <code>prototype</code></li>
|
||||
<li>访问对象属性时,先在自身查找,找不到就沿着原型链向上查找</li>
|
||||
|
||||
@@ -20,82 +20,162 @@ const refReset = () => { refStep.value = 0; objData.value.age = 25 }
|
||||
|
||||
<template>
|
||||
<div class="reference-demo">
|
||||
<div class="demo-title">🔄 值 vs 引用</div>
|
||||
<div class="demo-title">
|
||||
🔄 值 vs 引用
|
||||
</div>
|
||||
|
||||
<div class="compare-grid">
|
||||
<!-- 左侧:基本类型 -->
|
||||
<div class="compare-box">
|
||||
<div class="box-header blue">基本类型(复制值)</div>
|
||||
<div class="box-header blue">
|
||||
基本类型(复制值)
|
||||
</div>
|
||||
|
||||
<div class="memory-area">
|
||||
<div class="vars-row">
|
||||
<div class="var-item" :class="{ active: basicStep >= 0 }">
|
||||
<div
|
||||
class="var-item"
|
||||
:class="{ active: basicStep >= 0 }"
|
||||
>
|
||||
<span class="var-label">a</span>
|
||||
<span class="var-val">{{ basicA }}</span>
|
||||
</div>
|
||||
<div class="var-item" :class="{ active: basicStep >= 1, changed: basicStep >= 2 }">
|
||||
<div
|
||||
class="var-item"
|
||||
:class="{ active: basicStep >= 1, changed: basicStep >= 2 }"
|
||||
>
|
||||
<span class="var-label">b</span>
|
||||
<span class="var-val">{{ basicB ?? '?' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="copy-arrow" v-if="basicStep >= 1">↓ 复制值</div>
|
||||
<div
|
||||
v-if="basicStep >= 1"
|
||||
class="copy-arrow"
|
||||
>
|
||||
↓ 复制值
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result-text" :class="basicStep === 2 ? 'success' : 'info'">
|
||||
<div
|
||||
class="result-text"
|
||||
:class="basicStep === 2 ? 'success' : 'info'"
|
||||
>
|
||||
{{ basicStep === 0 ? '点击复制' : basicStep === 1 ? 'b 得到 10' : '✅ 修改 b 不影响 a' }}
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<button @click="basicCopy" :disabled="basicStep >= 1">复制</button>
|
||||
<button @click="basicModify" :disabled="basicStep !== 1">改 b</button>
|
||||
<button @click="basicReset" class="reset">重置</button>
|
||||
<button
|
||||
:disabled="basicStep >= 1"
|
||||
@click="basicCopy"
|
||||
>
|
||||
复制
|
||||
</button>
|
||||
<button
|
||||
:disabled="basicStep !== 1"
|
||||
@click="basicModify"
|
||||
>
|
||||
改 b
|
||||
</button>
|
||||
<button
|
||||
class="reset"
|
||||
@click="basicReset"
|
||||
>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:引用类型 -->
|
||||
<div class="compare-box">
|
||||
<div class="box-header orange">引用类型(复制地址)</div>
|
||||
<div class="box-header orange">
|
||||
引用类型(复制地址)
|
||||
</div>
|
||||
|
||||
<div class="memory-area">
|
||||
<div class="vars-row">
|
||||
<div class="var-item" :class="{ active: refStep >= 0 }">
|
||||
<div
|
||||
class="var-item"
|
||||
:class="{ active: refStep >= 0 }"
|
||||
>
|
||||
<span class="var-label">obj1</span>
|
||||
<span class="var-addr">0x001</span>
|
||||
</div>
|
||||
<div class="var-item" :class="{ active: refStep >= 1 }">
|
||||
<div
|
||||
class="var-item"
|
||||
:class="{ active: refStep >= 1 }"
|
||||
>
|
||||
<span class="var-label">obj2</span>
|
||||
<span class="var-addr">{{ refStep >= 1 ? '0x001' : '?' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-box" :class="{ changed: refStep === 2, copied: refStep === 3 }">
|
||||
<div class="data-addr">0x001</div>
|
||||
<div class="data-content">{ age: {{ objData.age }} }</div>
|
||||
<div
|
||||
class="data-box"
|
||||
:class="{ changed: refStep === 2, copied: refStep === 3 }"
|
||||
>
|
||||
<div class="data-addr">
|
||||
0x001
|
||||
</div>
|
||||
<div class="data-content">
|
||||
{ age: {{ objData.age }} }
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="refStep >= 1"
|
||||
class="copy-arrow"
|
||||
>
|
||||
指向同一地址
|
||||
</div>
|
||||
<div class="copy-arrow" v-if="refStep >= 1">指向同一地址</div>
|
||||
</div>
|
||||
|
||||
<div class="result-text" :class="refStep === 2 ? 'warning' : refStep === 3 ? 'success' : 'info'">
|
||||
<div
|
||||
class="result-text"
|
||||
:class="refStep === 2 ? 'warning' : refStep === 3 ? 'success' : 'info'"
|
||||
>
|
||||
{{ refStep === 0 ? '点击复制' : refStep === 1 ? '共享地址' : refStep === 2 ? '⚠️ 一改全变' : '✅ 已分离' }}
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<button @click="refCopy" :disabled="refStep >= 1">复制</button>
|
||||
<button @click="refModify" :disabled="refStep !== 1">修改</button>
|
||||
<button @click="refSpread" :disabled="refStep !== 2">展开</button>
|
||||
<button @click="refReset" class="reset">重置</button>
|
||||
<button
|
||||
:disabled="refStep >= 1"
|
||||
@click="refCopy"
|
||||
>
|
||||
复制
|
||||
</button>
|
||||
<button
|
||||
:disabled="refStep !== 1"
|
||||
@click="refModify"
|
||||
>
|
||||
修改
|
||||
</button>
|
||||
<button
|
||||
:disabled="refStep !== 2"
|
||||
@click="refSpread"
|
||||
>
|
||||
展开
|
||||
</button>
|
||||
<button
|
||||
class="reset"
|
||||
@click="refReset"
|
||||
>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="code-compare">
|
||||
<div class="code-col">
|
||||
<div class="code-title">基本类型</div>
|
||||
<div class="code-title">
|
||||
基本类型
|
||||
</div>
|
||||
<pre><code>let a = 10
|
||||
let b = a // b=10
|
||||
b = 20 // a还是10</code></pre>
|
||||
</div>
|
||||
<div class="code-col">
|
||||
<div class="code-title">引用类型</div>
|
||||
<div class="code-title">
|
||||
引用类型
|
||||
</div>
|
||||
<pre><code>let obj1 = {age:25}
|
||||
let obj2 = obj1
|
||||
obj2.age=30 // obj1也变了!
|
||||
|
||||
@@ -52,10 +52,10 @@ updateExplanation()
|
||||
<button
|
||||
v-for="scope in scopes"
|
||||
:key="scope.id"
|
||||
@click="activeScope = scope.id; updateExplanation()"
|
||||
class="scope-btn"
|
||||
:class="{ active: activeScope === scope.id }"
|
||||
:style="{ borderColor: scope.color }"
|
||||
@click="activeScope = scope.id; updateExplanation()"
|
||||
>
|
||||
{{ scope.name }}
|
||||
</button>
|
||||
@@ -71,7 +71,10 @@ updateExplanation()
|
||||
:class="{ active: activeScope === scope.id, dimmed: activeScope !== scope.id }"
|
||||
:style="{ borderLeftColor: scope.color }"
|
||||
>
|
||||
<div class="level-header" :style="{ color: scope.color }">
|
||||
<div
|
||||
class="level-header"
|
||||
:style="{ color: scope.color }"
|
||||
>
|
||||
{{ scope.name }}
|
||||
</div>
|
||||
<div class="level-vars">
|
||||
@@ -83,7 +86,10 @@ updateExplanation()
|
||||
>
|
||||
<span class="var-name">{{ v.name }}</span>
|
||||
<span class="var-value">= {{ v.value }}</span>
|
||||
<span v-if="!v.own" class="var-from">← {{ v.from }}</span>
|
||||
<span
|
||||
v-if="!v.own"
|
||||
class="var-from"
|
||||
>← {{ v.from }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,8 +97,12 @@ updateExplanation()
|
||||
|
||||
<!-- 说明 -->
|
||||
<div class="explanation-box">
|
||||
<div class="explanation-title">💡 当前位置可见的变量</div>
|
||||
<div class="explanation-text">{{ explanation }}</div>
|
||||
<div class="explanation-title">
|
||||
💡 当前位置可见的变量
|
||||
</div>
|
||||
<div class="explanation-text">
|
||||
{{ explanation }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -16,89 +16,148 @@
|
||||
<button
|
||||
v-for="scenario in scenarios"
|
||||
:key="scenario.id"
|
||||
@click="activeScenario = scenario.id"
|
||||
class="scenario-btn"
|
||||
:class="{ active: activeScenario === scenario.id }"
|
||||
@click="activeScenario = scenario.id"
|
||||
>
|
||||
{{ scenario.label }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 方法调用 -->
|
||||
<div v-if="activeScenario === 'method'" class="scenario-content">
|
||||
<div
|
||||
v-if="activeScenario === 'method'"
|
||||
class="scenario-content"
|
||||
>
|
||||
<div class="split-view">
|
||||
<div class="code-panel">
|
||||
<div class="code-title">对象方法调用</div>
|
||||
<div class="code-title">
|
||||
对象方法调用
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">const person = {</div>
|
||||
<div class="code-line indent">name: "张三",</div>
|
||||
<div class="code-line indent">greet: function() {</div>
|
||||
<div class="code-line indent indent">return "你好,我是" + this.name</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">person.greet() <span class="comment">// this → person</span></div>
|
||||
<div class="code-line">
|
||||
const person = {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
name: "张三",
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
greet: function() {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
return "你好,我是" + this.name
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
person.greet() <span class="comment">// this → person</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visual-panel">
|
||||
<div class="object-visual">
|
||||
<div class="object-box">
|
||||
<div class="object-title">person 对象</div>
|
||||
<div class="object-title">
|
||||
person 对象
|
||||
</div>
|
||||
<div class="object-content">
|
||||
<div class="property">name: "张三"</div>
|
||||
<div class="method" @click="simulateMethodCall">
|
||||
<div class="property">
|
||||
name: "张三"
|
||||
</div>
|
||||
<div
|
||||
class="method"
|
||||
@click="simulateMethodCall"
|
||||
>
|
||||
greet: function() { ... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-indicator">
|
||||
<div class="this-pointer">this →</div>
|
||||
<div class="this-pointer">
|
||||
this →
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="methodCallResult" class="result-box">
|
||||
<div
|
||||
v-if="methodCallResult"
|
||||
class="result-box"
|
||||
>
|
||||
{{ methodCallResult }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rule-box">
|
||||
<div class="rule-title">规则:对象方法</div>
|
||||
<div class="rule-content">通过对象调用方法时,<code>this</code> 指向该对象</div>
|
||||
<div class="rule-title">
|
||||
规则:对象方法
|
||||
</div>
|
||||
<div class="rule-content">
|
||||
通过对象调用方法时,<code>this</code> 指向该对象
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 普通函数 -->
|
||||
<div v-else-if="activeScenario === 'function'" class="scenario-content">
|
||||
<div
|
||||
v-else-if="activeScenario === 'function'"
|
||||
class="scenario-content"
|
||||
>
|
||||
<div class="split-view">
|
||||
<div class="code-panel">
|
||||
<div class="code-title">普通函数调用</div>
|
||||
<div class="code-title">
|
||||
普通函数调用
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">function show() {</div>
|
||||
<div class="code-line indent">return this === window</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">show() <span class="comment">// this → window (浏览器)</span></div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// 严格模式下是 undefined</div>
|
||||
<div class="code-line">
|
||||
function show() {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return this === window
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
show() <span class="comment">// this → window (浏览器)</span>
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// 严格模式下是 undefined
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visual-panel">
|
||||
<div class="function-visual">
|
||||
<div class="global-window">
|
||||
<div class="window-title">window (全局对象)</div>
|
||||
<div class="window-title">
|
||||
window (全局对象)
|
||||
</div>
|
||||
<div class="window-content">
|
||||
<div class="global-item">show 函数在这里</div>
|
||||
<div class="global-item">this → window</div>
|
||||
<div class="global-item">
|
||||
show 函数在这里
|
||||
</div>
|
||||
<div class="global-item">
|
||||
this → window
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mode-toggle">
|
||||
<button @click="strictMode = !strictMode" class="toggle-btn">
|
||||
<button
|
||||
class="toggle-btn"
|
||||
@click="strictMode = !strictMode"
|
||||
>
|
||||
{{ strictMode ? '严格模式:开' : '严格模式:关' }}
|
||||
</button>
|
||||
<div class="mode-result">
|
||||
@@ -107,7 +166,9 @@
|
||||
</div>
|
||||
|
||||
<div class="rule-box">
|
||||
<div class="rule-title">规则:普通函数</div>
|
||||
<div class="rule-title">
|
||||
规则:普通函数
|
||||
</div>
|
||||
<div class="rule-content">
|
||||
非严格模式:<code>this</code> 指向全局对象<br>
|
||||
严格模式:<code>this</code> 是 <code>undefined</code>
|
||||
@@ -118,20 +179,39 @@
|
||||
</div>
|
||||
|
||||
<!-- 构造函数 -->
|
||||
<div v-else-if="activeScenario === 'constructor'" class="scenario-content">
|
||||
<div
|
||||
v-else-if="activeScenario === 'constructor'"
|
||||
class="scenario-content"
|
||||
>
|
||||
<div class="split-view">
|
||||
<div class="code-panel">
|
||||
<div class="code-title">构造函数调用</div>
|
||||
<div class="code-title">
|
||||
构造函数调用
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">function Person(name) {</div>
|
||||
<div class="code-line indent">this.name = name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">const p1 = new Person("李四")</div>
|
||||
<div class="code-line">const p2 = new Person("王五")</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line comment">// p1.name = "李四"</div>
|
||||
<div class="code-line comment">// p2.name = "王五"</div>
|
||||
<div class="code-line">
|
||||
function Person(name) {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
this.name = name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
const p1 = new Person("李四")
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const p2 = new Person("王五")
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line comment">
|
||||
// p1.name = "李四"
|
||||
</div>
|
||||
<div class="code-line comment">
|
||||
// p2.name = "王五"
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,17 +222,23 @@
|
||||
<span class="step-num">1</span>
|
||||
<span>创建新对象</span>
|
||||
</div>
|
||||
<div class="process-arrow">↓</div>
|
||||
<div class="process-arrow">
|
||||
↓
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<span class="step-num">2</span>
|
||||
<span>this 指向新对象</span>
|
||||
</div>
|
||||
<div class="process-arrow">↓</div>
|
||||
<div class="process-arrow">
|
||||
↓
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<span class="step-num">3</span>
|
||||
<span>执行构造函数</span>
|
||||
</div>
|
||||
<div class="process-arrow">↓</div>
|
||||
<div class="process-arrow">
|
||||
↓
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<span class="step-num">4</span>
|
||||
<span>返回新对象</span>
|
||||
@@ -161,18 +247,28 @@
|
||||
|
||||
<div class="object-comparison">
|
||||
<div class="obj-instance">
|
||||
<div class="obj-title">p1</div>
|
||||
<div class="obj-content">name: "李四"</div>
|
||||
<div class="obj-title">
|
||||
p1
|
||||
</div>
|
||||
<div class="obj-content">
|
||||
name: "李四"
|
||||
</div>
|
||||
</div>
|
||||
<div class="obj-instance">
|
||||
<div class="obj-title">p2</div>
|
||||
<div class="obj-content">name: "王五"</div>
|
||||
<div class="obj-title">
|
||||
p2
|
||||
</div>
|
||||
<div class="obj-content">
|
||||
name: "王五"
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rule-box">
|
||||
<div class="rule-title">规则:new 调用</div>
|
||||
<div class="rule-title">
|
||||
规则:new 调用
|
||||
</div>
|
||||
<div class="rule-content">
|
||||
使用 <code>new</code> 调用函数时,<code>this</code> 指向新创建的对象
|
||||
</div>
|
||||
@@ -182,52 +278,104 @@
|
||||
</div>
|
||||
|
||||
<!-- call/apply/bind -->
|
||||
<div v-else-if="activeScenario === 'explicit'" class="scenario-content">
|
||||
<div
|
||||
v-else-if="activeScenario === 'explicit'"
|
||||
class="scenario-content"
|
||||
>
|
||||
<div class="split-view">
|
||||
<div class="code-panel">
|
||||
<div class="code-title">显式绑定 (call/apply/bind)</div>
|
||||
<div class="code-title">
|
||||
显式绑定 (call/apply/bind)
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">function greet() {</div>
|
||||
<div class="code-line indent">return "我是" + this.name</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">const person = { name: "小明" }</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">greet.call(person) <span class="comment">// 显式指定 this</span></div>
|
||||
<div class="code-line">greet.apply(person)</div>
|
||||
<div class="code-line">const bound = greet.bind(person)</div>
|
||||
<div class="code-line">
|
||||
function greet() {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
return "我是" + this.name
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
const person = { name: "小明" }
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
greet.call(person) <span class="comment">// 显式指定 this</span>
|
||||
</div>
|
||||
<div class="code-line">
|
||||
greet.apply(person)
|
||||
</div>
|
||||
<div class="code-line">
|
||||
const bound = greet.bind(person)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visual-panel">
|
||||
<div class="binding-visual">
|
||||
<div class="function-box">
|
||||
<div class="box-title">greet 函数</div>
|
||||
<div class="box-content">this.name</div>
|
||||
<div class="box-title">
|
||||
greet 函数
|
||||
</div>
|
||||
<div class="box-content">
|
||||
this.name
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="binding-methods">
|
||||
<div class="binding-item" @click="simulateCall" :class="{ active: bindingMethod === 'call' }">
|
||||
<div class="method-name">call(person)</div>
|
||||
<div class="method-desc">立即调用,this → person</div>
|
||||
<div
|
||||
class="binding-item"
|
||||
:class="{ active: bindingMethod === 'call' }"
|
||||
@click="simulateCall"
|
||||
>
|
||||
<div class="method-name">
|
||||
call(person)
|
||||
</div>
|
||||
<div class="method-desc">
|
||||
立即调用,this → person
|
||||
</div>
|
||||
</div>
|
||||
<div class="binding-item" @click="simulateApply" :class="{ active: bindingMethod === 'apply' }">
|
||||
<div class="method-name">apply(person)</div>
|
||||
<div class="method-desc">同 call,参数为数组</div>
|
||||
<div
|
||||
class="binding-item"
|
||||
:class="{ active: bindingMethod === 'apply' }"
|
||||
@click="simulateApply"
|
||||
>
|
||||
<div class="method-name">
|
||||
apply(person)
|
||||
</div>
|
||||
<div class="method-desc">
|
||||
同 call,参数为数组
|
||||
</div>
|
||||
</div>
|
||||
<div class="binding-item" @click="simulateBind" :class="{ active: bindingMethod === 'bind' }">
|
||||
<div class="method-name">bind(person)</div>
|
||||
<div class="method-desc">返回新函数,this 固定</div>
|
||||
<div
|
||||
class="binding-item"
|
||||
:class="{ active: bindingMethod === 'bind' }"
|
||||
@click="simulateBind"
|
||||
>
|
||||
<div class="method-name">
|
||||
bind(person)
|
||||
</div>
|
||||
<div class="method-desc">
|
||||
返回新函数,this 固定
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="bindingResult" class="binding-result">
|
||||
<div
|
||||
v-if="bindingResult"
|
||||
class="binding-result"
|
||||
>
|
||||
{{ bindingResult }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rule-box">
|
||||
<div class="rule-title">规则:显式绑定</div>
|
||||
<div class="rule-title">
|
||||
规则:显式绑定
|
||||
</div>
|
||||
<div class="rule-content">
|
||||
<code>call/apply/bind</code> 可以显式指定 <code>this</code> 的指向
|
||||
</div>
|
||||
@@ -237,48 +385,85 @@
|
||||
</div>
|
||||
|
||||
<!-- 箭头函数 -->
|
||||
<div v-else class="scenario-content">
|
||||
<div
|
||||
v-else
|
||||
class="scenario-content"
|
||||
>
|
||||
<div class="split-view">
|
||||
<div class="code-panel">
|
||||
<div class="code-title">箭头函数的 this</div>
|
||||
<div class="code-title">
|
||||
箭头函数的 this
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-line">const person = {</div>
|
||||
<div class="code-line indent">name: "小红",</div>
|
||||
<div class="code-line indent">greet: function() {</div>
|
||||
<div class="code-line indent indent">setTimeout(() => {</div>
|
||||
<div class="code-line indent indent indent">console.log(this.name)</div>
|
||||
<div class="code-line indent indent">}, 1000)</div>
|
||||
<div class="code-line indent">}</div>
|
||||
<div class="code-line">}</div>
|
||||
<div class="code-line"></div>
|
||||
<div class="code-line">person.greet() <span class="comment">// 输出 "小红"</span></div>
|
||||
<div class="code-line">
|
||||
const person = {
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
name: "小红",
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
greet: function() {
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
setTimeout(() => {
|
||||
</div>
|
||||
<div class="code-line indent indent indent">
|
||||
console.log(this.name)
|
||||
</div>
|
||||
<div class="code-line indent indent">
|
||||
}, 1000)
|
||||
</div>
|
||||
<div class="code-line indent">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line">
|
||||
}
|
||||
</div>
|
||||
<div class="code-line" />
|
||||
<div class="code-line">
|
||||
person.greet() <span class="comment">// 输出 "小红"</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visual-panel">
|
||||
<div class="arrow-function-visual">
|
||||
<div class="outer-context">
|
||||
<div class="context-title">外层作用域 (person)</div>
|
||||
<div class="context-title">
|
||||
外层作用域 (person)
|
||||
</div>
|
||||
<div class="context-content">
|
||||
<div class="context-item">this.name = "小红"</div>
|
||||
<div class="context-item">
|
||||
this.name = "小红"
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-capture">
|
||||
<div class="capture-title">箭头函数捕获外层 this</div>
|
||||
<div class="capture-arrow">↑ 继承 this</div>
|
||||
<div class="capture-title">
|
||||
箭头函数捕获外层 this
|
||||
</div>
|
||||
<div class="capture-arrow">
|
||||
↑ 继承 this
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inner-context">
|
||||
<div class="context-title">箭头函数内部</div>
|
||||
<div class="context-title">
|
||||
箭头函数内部
|
||||
</div>
|
||||
<div class="context-content">
|
||||
<div class="context-item">this → 外层的 this</div>
|
||||
<div class="context-item">
|
||||
this → 外层的 this
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rule-box">
|
||||
<div class="rule-title">规则:箭头函数</div>
|
||||
<div class="rule-title">
|
||||
规则:箭头函数
|
||||
</div>
|
||||
<div class="rule-content">
|
||||
箭头函数没有自己的 <code>this</code>,它继承外层作用域的 <code>this</code>
|
||||
</div>
|
||||
@@ -288,7 +473,9 @@
|
||||
</div>
|
||||
|
||||
<div class="quick-reference">
|
||||
<div class="reference-title">📋 this 指向速查表</div>
|
||||
<div class="reference-title">
|
||||
📋 this 指向速查表
|
||||
</div>
|
||||
<div class="reference-table">
|
||||
<div class="ref-row header">
|
||||
<span>调用方式</span>
|
||||
|
||||
@@ -44,36 +44,85 @@ const reset = () => {
|
||||
</div>
|
||||
|
||||
<div class="boxes-row">
|
||||
<div class="var-box" :class="{ error: messageType === 'error' }">
|
||||
<div class="box-tag const">const</div>
|
||||
<div class="box-name">name</div>
|
||||
<div class="box-value">{{ name }}</div>
|
||||
<div class="box-lock">🔒</div>
|
||||
<div
|
||||
class="var-box"
|
||||
:class="{ error: messageType === 'error' }"
|
||||
>
|
||||
<div class="box-tag const">
|
||||
const
|
||||
</div>
|
||||
<div class="box-name">
|
||||
name
|
||||
</div>
|
||||
<div class="box-value">
|
||||
{{ name }}
|
||||
</div>
|
||||
<div class="box-lock">
|
||||
🔒
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="var-box" :class="{ success: messageType === 'success' }">
|
||||
<div class="box-tag let">let</div>
|
||||
<div class="box-name">age</div>
|
||||
<div class="box-value">{{ age }}</div>
|
||||
<div class="box-lock">🔓</div>
|
||||
<div
|
||||
class="var-box"
|
||||
:class="{ success: messageType === 'success' }"
|
||||
>
|
||||
<div class="box-tag let">
|
||||
let
|
||||
</div>
|
||||
<div class="box-name">
|
||||
age
|
||||
</div>
|
||||
<div class="box-value">
|
||||
{{ age }}
|
||||
</div>
|
||||
<div class="box-lock">
|
||||
🔓
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="var-box">
|
||||
<div class="box-tag const">const</div>
|
||||
<div class="box-name">isStudent</div>
|
||||
<div class="box-value">{{ isStudent }}</div>
|
||||
<div class="box-lock">🔒</div>
|
||||
<div class="box-tag const">
|
||||
const
|
||||
</div>
|
||||
<div class="box-name">
|
||||
isStudent
|
||||
</div>
|
||||
<div class="box-value">
|
||||
{{ isStudent }}
|
||||
</div>
|
||||
<div class="box-lock">
|
||||
🔒
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="message" v-if="showMessage" :class="messageType">
|
||||
<div
|
||||
v-if="showMessage"
|
||||
class="message"
|
||||
:class="messageType"
|
||||
>
|
||||
{{ showMessage }}
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button @click="modifyAge" class="btn btn-primary">修改 age</button>
|
||||
<button @click="modifyName" class="btn btn-danger">修改 name</button>
|
||||
<button @click="reset" class="btn btn-secondary">重置</button>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@click="modifyAge"
|
||||
>
|
||||
修改 age
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
@click="modifyName"
|
||||
>
|
||||
修改 name
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-secondary"
|
||||
@click="reset"
|
||||
>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="code-snippet">
|
||||
|
||||
@@ -15,32 +15,58 @@
|
||||
|
||||
<div class="code-display">
|
||||
<div class="code-block">
|
||||
<div class="code-line" v-for="(line, i) in codeLines" :key="i" :class="{ active: currentLine === i }">
|
||||
<div
|
||||
v-for="(line, i) in codeLines"
|
||||
:key="i"
|
||||
class="code-line"
|
||||
:class="{ active: currentLine === i }"
|
||||
>
|
||||
<span class="line-num">{{ i + 1 }}</span>
|
||||
<span class="line-code" v-html="highlightCode(line)"></span>
|
||||
<span
|
||||
class="line-code"
|
||||
v-html="highlightCode(line)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visualization">
|
||||
<div class="scope-area global-scope">
|
||||
<div class="scope-title">全局作用域(房子外)</div>
|
||||
<div class="scope-title">
|
||||
全局作用域(房子外)
|
||||
</div>
|
||||
<div class="scope-vars">
|
||||
<div v-if="step >= 1" class="var-item" :class="{ error: step === 4 }">
|
||||
<div
|
||||
v-if="step >= 1"
|
||||
class="var-item"
|
||||
:class="{ error: step === 4 }"
|
||||
>
|
||||
<span class="var-type">var</span>
|
||||
<span class="var-name">globalVar</span>
|
||||
<span class="var-value">= "外面"</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scope-area block-scope" v-if="step >= 2">
|
||||
<div class="scope-title">块级作用域(房间内)</div>
|
||||
<div
|
||||
v-if="step >= 2"
|
||||
class="scope-area block-scope"
|
||||
>
|
||||
<div class="scope-title">
|
||||
块级作用域(房间内)
|
||||
</div>
|
||||
<div class="scope-vars">
|
||||
<div v-if="step >= 2" class="var-item" :class="{ error: step === 4 }">
|
||||
<div
|
||||
v-if="step >= 2"
|
||||
class="var-item"
|
||||
:class="{ error: step === 4 }"
|
||||
>
|
||||
<span class="var-type">var</span>
|
||||
<span class="var-name">blockVar</span>
|
||||
<span class="var-value">= "房间里"</span>
|
||||
</div>
|
||||
<div v-if="step >= 3" class="var-item let">
|
||||
<div
|
||||
v-if="step >= 3"
|
||||
class="var-item let"
|
||||
>
|
||||
<span class="var-type">let</span>
|
||||
<span class="var-name">blockLet</span>
|
||||
<span class="var-value">= "只有房间内能用"</span>
|
||||
@@ -50,9 +76,16 @@
|
||||
</div>
|
||||
|
||||
<div class="console-output">
|
||||
<div class="console-title">控制台输出</div>
|
||||
<div class="console-title">
|
||||
控制台输出
|
||||
</div>
|
||||
<div class="console-lines">
|
||||
<div v-for="(output, i) in consoleOutput" :key="i" class="console-line" :class="{ error: output.error }">
|
||||
<div
|
||||
v-for="(output, i) in consoleOutput"
|
||||
:key="i"
|
||||
class="console-line"
|
||||
:class="{ error: output.error }"
|
||||
>
|
||||
{{ output.text }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -61,10 +94,27 @@
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button @click="prevStep" :disabled="step === 0" class="control-btn">← 上一步</button>
|
||||
<button
|
||||
:disabled="step === 0"
|
||||
class="control-btn"
|
||||
@click="prevStep"
|
||||
>
|
||||
← 上一步
|
||||
</button>
|
||||
<span class="step-indicator">{{ step + 1 }} / {{ maxSteps }}</span>
|
||||
<button @click="nextStep" :disabled="step === maxSteps" class="control-btn">下一步 →</button>
|
||||
<button @click="reset" class="control-btn secondary">重置</button>
|
||||
<button
|
||||
:disabled="step === maxSteps"
|
||||
class="control-btn"
|
||||
@click="nextStep"
|
||||
>
|
||||
下一步 →
|
||||
</button>
|
||||
<button
|
||||
class="control-btn secondary"
|
||||
@click="reset"
|
||||
>
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
|
||||
Reference in New Issue
Block a user