feat(docs): enhance interactive demos and improve documentation

- Add new interactive components for frontend routing, browser rendering pipeline, and database transactions
- Improve existing demos with better visuals, explanations, and examples
- Update documentation structure and content for better clarity
- Add new utility scripts and update package.json with new commands
- Fix formatting and alignment in documentation tables
This commit is contained in:
sanbuphy
2026-02-13 22:10:03 +08:00
parent 599052b2e0
commit d174ceea32
88 changed files with 26273 additions and 15539 deletions
@@ -1,5 +1,15 @@
<template>
<div class="backend-languages-demo">
<div class="demo-header">
<span class="icon">🛠</span>
<span class="title">后端语言工具箱</span>
<span class="subtitle">选择合适的工具完成工作</span>
</div>
<div class="intro-text">
想象你是一名<span class="highlight">建筑工人</span>搬砖用铁铲砌墙用瓦刀装修用刷子后端语言也一样不同场景适合不同的"工具"没有最好的语言只有最合适的选择
</div>
<div class="language-grid">
<div
v-for="lang in languages"
@@ -8,470 +18,286 @@
:class="{ active: selectedLang === lang.name }"
@click="selectedLang = lang.name"
>
<div class="lang-header">
<div class="lang-icon">{{ lang.icon }}</div>
<h4>{{ lang.name }}</h4>
<div class="lang-year">{{ lang.year }}</div>
</div>
<div class="lang-tags">
<span
v-for="tag in lang.tags"
:key="tag"
class="tag"
:class="`tag-${tag.type}`"
>
{{ tag.label }}
</span>
</div>
<div class="lang-icon">{{ lang.icon }}</div>
<div class="lang-name">{{ lang.name }}</div>
<div class="lang-metaphor">{{ lang.metaphor }}</div>
<div class="lang-description">{{ lang.description }}</div>
<div class="lang-stats">
<div class="stat">
<span class="stat-label">性能</span>
<div class="stat-bar">
<div
class="stat-fill performance"
:style="{ width: lang.stats.performance + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">开发效率</span>
<div class="stat-bar">
<div
class="stat-fill efficiency"
:style="{ width: lang.stats.efficiency + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">生态</span>
<div class="stat-bar">
<div
class="stat-fill ecosystem"
:style="{ width: lang.stats.ecosystem + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">学习曲线</span>
<div class="stat-bar">
<div
class="stat-fill learning"
:style="{ width: lang.stats.learning + '%' }"
></div>
</div>
</div>
</div>
</div>
</div>
<transition name="fade">
<Transition name="fade">
<div v-if="selectedLang" class="lang-detail">
<h3>{{ getLangDetail(selectedLang).title }}</h3>
<div class="detail-grid">
<div class="detail-header">
<span class="detail-icon">{{ getCurrentLang().icon }}</span>
<span class="detail-title">{{ getCurrentLang().name }}</span>
</div>
<div class="detail-sections">
<div class="detail-section">
<h4>核心特点</h4>
<h6>🎯 适用场景</h6>
<ul>
<li
v-for="feature in getLangDetail(selectedLang).features"
:key="feature"
>
{{ feature }}
<li v-for="scenario in getCurrentLang().scenarios" :key="scenario">
{{ scenario }}
</li>
</ul>
</div>
<div class="detail-section">
<h4>典型应用</h4>
<h6> 优势</h6>
<ul>
<li
v-for="app in getLangDetail(selectedLang).applications"
:key="app"
>
{{ app }}
</li>
<li v-for="pro in getCurrentLang().pros" :key="pro">{{ pro }}</li>
</ul>
</div>
<div class="detail-section">
<h4>劣势</h4>
<div class="pros-cons">
<div class="pros">
<strong>优势</strong>
<ul>
<li
v-for="pro in getLangDetail(selectedLang).pros"
:key="pro"
>
{{ pro }}
</li>
</ul>
</div>
<div class="cons">
<strong>劣势</strong>
<ul>
<li
v-for="con in getLangDetail(selectedLang).cons"
:key="con"
>
{{ con }}
</li>
</ul>
</div>
</div>
<h6> 劣势</h6>
<ul>
<li v-for="con in getCurrentLang().cons" :key="con">{{ con }}</li>
</ul>
</div>
</div>
</div>
</transition>
</Transition>
<div v-if="!selectedLang" class="hint-text">
👆 点击上方任意语言查看详细说明
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>选择语言时先想清楚"我要解决什么问题"而不是"哪个语言最火"初创公司选 Python/Node.js 快速验证大厂选 Java/Go 保证稳定游戏开发选 C++ 追求极致性能
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selectedLang = ref('Java')
const selectedLang = ref('Go')
const languages = [
{
name: 'Java',
icon: '',
year: '1995',
tags: [
{ type: 'primary', label: '企业级' },
{ type: 'success', label: '跨平台' },
{ type: 'info', label: '强类型' }
name: 'Go',
icon: '🐹',
metaphor: '电动螺丝刀',
description: '云原生时代的高效工具',
scenarios: [
'微服务架构(Docker、K8s 都是 Go 写的)',
'高并发 API 服务',
'DevOps 工具开发',
'区块链基础设施'
],
description: '企业级开发的霸主,Spring Boot 生态成熟',
stats: { performance: 75, efficiency: 60, ecosystem: 95, learning: 40 }
pros: [
'并发性能优秀(Goroutine 轻量级协程)',
'编译快,部署简单(单一可执行文件)',
'语法简洁,学习曲线平缓',
'内存占用低,性能接近 C++'
],
cons: [
'生态不如 Java/Python 成熟',
'错误处理繁琐(if err != nil',
'泛型支持较弱(Go 1.18+ 引入)',
'不适合 CPU 密集型任务'
]
},
{
name: 'Python',
icon: '🐍',
year: '1991',
tags: [
{ type: 'primary', label: 'AI/ML' },
{ type: 'success', label: '简洁' },
{ type: 'warning', label: '动态类型' }
metaphor: '瑞士军刀',
description: '什么都能干的全能工具',
scenarios: [
'AI/机器学习(PyTorch、TensorFlow',
'数据分析和处理',
'快速原型开发',
'自动化脚本'
],
description: 'AI 与数据分析的首选语言',
stats: { performance: 30, efficiency: 95, ecosystem: 95, learning: 95 }
pros: [
'语法极简,学习曲线平缓',
'AI 生态无与伦比',
'开发速度快,代码量少',
'库丰富,几乎任何功能都有现成方案'
],
cons: [
'运行速度慢(比 Go/Java 慢 10-100 倍)',
'GIL 限制多线程性能',
'打包部署复杂(依赖地狱)',
'动态类型,运行时错误多'
]
},
{
name: 'Go',
icon: '🐹',
year: '2009',
tags: [
{ type: 'primary', label: '云原生' },
{ type: 'success', label: '高性能' },
{ type: 'info', label: '并发' }
],
description: 'Google 出品,云原生时代的宠儿',
stats: { performance: 90, efficiency: 85, ecosystem: 75, learning: 80 }
},
{
name: 'Node.js',
icon: '💚',
year: '2009',
tags: [
{ type: 'primary', label: '全栈' },
{ type: 'success', label: 'NPM' },
{ type: 'info', label: '异步' }
],
description: 'JavaScript 运行时,前后端统一',
stats: { performance: 70, efficiency: 85, ecosystem: 95, learning: 75 }
},
{
name: 'C#',
icon: '💜',
year: '2000',
tags: [
{ type: 'primary', label: '.NET' },
{ type: 'success', label: '跨平台' },
{ type: 'info', label: 'Unity' }
],
description: '微软出品,Windows 生态王者',
stats: { performance: 80, efficiency: 70, ecosystem: 85, learning: 50 }
},
{
name: 'Rust',
icon: '🦀',
year: '2010',
tags: [
{ type: 'primary', label: '系统级' },
{ type: 'success', label: '内存安全' },
{ type: 'danger', label: '难学' }
],
description: 'Mozilla 出品,内存安全的系统语言',
stats: { performance: 95, efficiency: 40, ecosystem: 70, learning: 20 }
},
{
name: 'C++',
icon: '⚡',
year: '1985',
tags: [
{ type: 'primary', label: '高性能' },
{ type: 'success', label: '游戏' },
{ type: 'danger', label: '复杂' }
],
description: '高性能计算的基石',
stats: { performance: 98, efficiency: 35, ecosystem: 90, learning: 25 }
},
{
name: 'Ruby',
icon: '💎',
year: '1995',
tags: [
{ type: 'primary', label: 'Rails' },
{ type: 'success', label: '优雅' },
{ type: 'warning', label: '慢' }
],
description: 'Ruby on Rails,快速开发典范',
stats: { performance: 25, efficiency: 90, ecosystem: 70, learning: 85 }
}
]
const langDetails = {
Java: {
title: 'Java - 企业级开发的霸主',
features: [
'JVM (Java Virtual Machine) 实现跨平台',
'强类型系统,编译时检查',
'Spring 全家桶生态成熟',
'JIT 编译器提供接近 C++ 的性能'
],
applications: [
name: 'Java',
icon: '',
metaphor: '重型挖掘机',
description: '企业级开发的稳定选择',
scenarios: [
'大型企业系统(银行、保险、电商)',
'Android 应用开发',
'大数据处理(Hadoop、Spark',
'微服务架构(Spring Cloud'
],
pros: [
'生态极其成熟,框架完备',
'强类型,编译时检查',
'多线程模型成熟',
'跨平台,JVM 优化强大'
'生态极其成熟,框架完备',
'强类型,编译时检查',
'多线程模型成熟',
'跨平台,JVM 优化强大'
],
cons: [
'代码冗长,样板代码多',
'启动慢,内存占用高',
'学习曲线陡峭(Spring 全家桶)',
'版本更新快,兼容性问题'
'代码冗长,样板代码多',
'启动慢,内存占用高',
'学习曲线陡峭(Spring 全家桶)',
'版本更新快,兼容性问题'
]
},
Python: {
title: 'Python - AI 与脚本之王',
features: [
'极简语法,像读英语一样',
'AI 生态无与伦比(NumPy、PyTorch',
'快速开发,代码量少',
'丰富的科学计算库'
],
applications: [
'AI/机器学习(所有主流框架)',
'数据分析(Pandas、Jupyter',
'脚本自动化(运维、数据处理)',
'Web 开发(Django、Flask'
],
pros: [
'✅ 语法简单,学习曲线平缓',
'✅ AI 生态无与伦比',
'✅ 快速开发,代码量少',
'✅ 社区活跃,库丰富'
],
cons: [
'❌ 运行速度慢(比 Java/Go 慢 10-100 倍)',
'❌ 动态类型,运行时错误多',
'❌ GIL 限制,多线程性能差',
'❌ 打包部署复杂(依赖地狱)'
]
},
Go: {
title: 'Go - 云原生时代的宠儿',
features: [
'Goroutine (协程) 轻量级并发',
'简洁语法,25 个关键字',
'快速编译,比 Java 快 10 倍',
'单一可执行文件,无依赖'
],
applications: [
'云原生基础设施(Docker、K8s',
'微服务架构',
'DevOps 工具(Terraform、Prometheus',
'区块链(Hyperledger Fabric'
],
pros: [
'✅ 原生并发,性能接近 C++',
'✅ 简洁语法,学习曲线平缓',
'✅ 编译快,部署简单',
'✅ 单一可执行文件,无依赖'
],
cons: [
'❌ 生态不如 Java/Python 成熟',
'❌ 错误处理繁琐(if err != nil',
'❌ 泛型支持较弱(Go 1.18+ 才引入)',
'❌ 不如 Java/Python 灵活'
]
},
'Node.js': {
title: 'Node.js - 全栈工程师的利器',
features: [
'事件驱动,非阻塞 I/O',
'前后端统一语言',
'NPM 世界最大的包仓库',
'适合实时应用'
],
applications: [
{
name: 'Node.js',
icon: '💚',
metaphor: '万能扳手',
description: '前后端统一的利器',
scenarios: [
'全栈 Web 应用(React + Node.js',
'实时系统(聊天应用、协作工具)',
'ServerlessAWS Lambda、Vercel',
'CLI 工具(VS Code、Webpack'
'I/O 密集型 API'
],
pros: [
'前后端统一,减少语言切换成本',
'NPM 生态庞大,库丰富',
'适合 I/O 密集型应用',
'✅ 社区活跃,更新快'
'前后端统一语言,减少切换成本',
'NPM 生态庞大,世界最大包仓库',
'适合 I/O 密集型应用',
'事件驱动,非阻塞 I/O'
],
cons: [
'单线程,CPU 密集型任务性能差',
'回调地狱(async/await 有改善)',
'动态类型,运行时错误多',
'版本兼容性问题多'
'单线程,CPU 密集型性能差',
'回调地狱(虽然 async/await 有改善)',
'动态类型,运行时错误多',
'版本兼容性问题多'
]
},
'C#': {
title: 'C# - Windows 生态的王者',
features: [
'微软 Visual Studio 极其强大',
'.NET Core 实现跨平台',
'高性能,CoreFX 优化',
'Unity 游戏开发官方语言'
],
applications: [
'Windows 应用开发',
'游戏开发(Unity 引擎)',
'Web 开发(ASP.NET Core',
'Azure 云服务'
],
pros: [
'✅ Visual Studio 极其强大',
'✅ ASP.NET Core 性能优秀',
'✅ 跨平台(.NET Core',
'✅ 游戏开发(Unity'
],
cons: [
'❌ Windows 历史包袱重',
'❌ 社区不如 Java/Python 活跃',
'❌ 学习曲线陡峭',
'❌ 开源生态相对较弱'
]
},
Rust: {
title: 'Rust - 系统级编程的未来',
features: [
'所有权系统保证内存安全',
'零成本抽象',
'编译时保证无内存泄漏',
'WebAssembly 支持'
],
applications: [
{
name: 'Rust',
icon: '🦀',
metaphor: '激光切割机',
description: '内存安全的系统级工具',
scenarios: [
'系统编程(操作系统、数据库)',
'区块链(Solana、Polkadot',
'WebAssembly(前端高性能计算)',
'基础设施(AWS Firecracker'
],
pros: [
'内存安全,无 GC',
'性能接近 C++',
'现代化语法',
'✅ WebAssembly 支持'
'内存安全,编译时保证无泄漏',
'性能接近 C++',
'现代化语法,零成本抽象',
'无 GC,运行时开销低'
],
cons: [
'学习曲线极其陡峭',
'编译时间长',
'生态不如 Go/Rust 成熟',
'开发速度慢'
'学习曲线极其陡峭',
'编译时间长',
'生态不如 Go/Java 成熟',
'开发速度慢'
]
},
'C++': {
title: 'C++ - 高性能计算的基石',
features: [
'极致性能,无语言能超越',
'底层控制,直接操作内存',
'游戏引擎标准',
'现代 C++ (11/14/17/20)'
],
applications: [
{
name: 'C++',
icon: '⚡',
metaphor: '工业电钻',
description: '高性能计算的基石',
scenarios: [
'游戏开发(Unreal Engine',
'高频交易(金融系统)',
'浏览器引擎(Chrome V8',
'AI 框架底层(PyTorch、TF'
],
pros: ['✅ 性能极致', '✅ 底层控制力强', '✅ 游戏开发标准', '✅ 生态成熟'],
cons: [
'❌ 学习曲线极其陡峭',
'❌ 内存管理复杂(易泄漏)',
'❌ 开发效率低',
'❌ 不适合 Web 开发'
]
},
Ruby: {
title: 'Ruby - 快速开发的典范',
features: ['Ruby on Rails 框架', '约定优于配置', '代码优雅', '快速开发'],
applications: [
'初创公司(GitHub、Airbnb',
'快速原型(MVP、黑客松)',
'Web 开发(Rails、Sinatra',
'CI/CD 脚本'
],
pros: [
'✅ Rails 框架极其成熟',
'✅ 快速开发,代码优雅',
'✅ 约定优于配置',
'✅ 社区活跃'
'性能极致,无语言能超越',
'底层控制力强,直接操作内存',
'游戏开发标准',
'生态成熟'
],
cons: [
'❌ 性能较差',
'❌ 动态类型,运行时错误多',
'❌ 多线程性能差',
'❌ 生态不如 Java/Python 广泛'
'学习曲线极其陡峭',
'内存管理复杂(易泄漏)',
'开发效率低',
'不适合 Web 开发'
]
}
}
]
const getLangDetail = (name) => {
return langDetails[name] || {}
const getCurrentLang = () => {
return languages.find(l => l.name === selectedLang.value) || languages[0]
}
</script>
<style scoped>
.backend-languages-demo {
border-radius: 16px;
background: var(--vp-c-bg);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
overflow: hidden;
margin: 2rem 0;
padding: 2rem;
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
max-height: 600px;
overflow-y: auto;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon {
font-size: 1.25rem;
}
.demo-header .title {
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
font-size: 0.85rem;
margin-left: 0.5rem;
}
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.language-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 0.75rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
margin-bottom: 1rem;
}
.language-card {
padding: 1rem;
background: var(--vp-c-bg-soft);
border: 2px solid transparent;
border-radius: 12px;
padding: 1.5rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
transition: all 0.2s ease;
text-align: center;
}
.language-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.language-card.active {
@@ -479,150 +305,72 @@ const getLangDetail = (name) => {
background: var(--vp-c-bg);
}
.lang-header {
.lang-icon {
font-size: 2rem;
margin-bottom: 0.5rem;
}
.lang-name {
font-weight: 600;
color: var(--vp-c-text-1);
margin-bottom: 0.25rem;
}
.lang-metaphor {
font-size: 0.8rem;
color: var(--vp-c-brand-1);
margin-bottom: 0.5rem;
font-weight: 500;
}
.lang-description {
font-size: 0.8rem;
color: var(--vp-c-text-2);
line-height: 1.4;
}
.hint-text {
text-align: center;
font-size: 0.85rem;
color: var(--vp-c-text-3);
margin: 0.75rem 0;
}
.lang-detail {
background: var(--vp-c-bg);
border-radius: 8px;
padding: 1rem;
margin-top: 0.75rem;
border: 1px solid var(--vp-c-divider);
}
.detail-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.lang-icon {
font-size: 2.5rem;
line-height: 1;
}
.lang-header h4 {
flex: 1;
margin: 0;
font-size: 1.2rem;
color: var(--vp-c-text-1);
}
.lang-year {
font-size: 0.8rem;
color: var(--vp-c-text-3);
font-family: var(--vp-font-family-mono);
}
.lang-tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-bottom: 1rem;
}
.tag {
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
}
.tag-primary {
background: #e0f2fe;
color: #0369a1;
}
.tag-success {
background: #dcfce7;
color: #15803d;
}
.tag-info {
background: #e0e7ff;
color: #4338ca;
}
.tag-warning {
background: #fef3c7;
color: #b45309;
}
.tag-danger {
background: #fee2e2;
color: #b91c1c;
}
.lang-description {
font-size: 0.9rem;
color: var(--vp-c-text-2);
margin-bottom: 1rem;
line-height: 1.5;
}
.lang-stats {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.stat {
display: flex;
align-items: center;
gap: 0.75rem;
}
.stat-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
min-width: 60px;
font-weight: 600;
}
.stat-bar {
flex: 1;
height: 8px;
background: var(--vp-c-divider);
border-radius: 4px;
overflow: hidden;
}
.stat-fill {
height: 100%;
border-radius: 4px;
transition: width 0.5s ease;
}
.stat-fill.performance {
background: linear-gradient(90deg, #fbbf24, #f59e0b);
}
.stat-fill.efficiency {
background: linear-gradient(90deg, #34d399, #10b981);
}
.stat-fill.ecosystem {
background: linear-gradient(90deg, #60a5fa, #3b82f6);
}
.stat-fill.learning {
background: linear-gradient(90deg, #f472b6, #ec4899);
}
.lang-detail {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 2rem;
animation: fade-in 0.3s ease;
}
.lang-detail h3 {
margin-top: 0;
margin-bottom: 1.5rem;
color: var(--vp-c-brand);
.detail-icon {
font-size: 1.5rem;
}
.detail-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
.detail-title {
font-weight: 600;
font-size: 1rem;
color: var(--vp-c-text-1);
}
.detail-section h4 {
.detail-sections {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.detail-section h6 {
margin: 0 0 0.5rem 0;
font-size: 0.9rem;
color: var(--vp-c-text-1);
margin-bottom: 1rem;
font-size: 1.1rem;
}
.detail-section ul {
@@ -632,12 +380,12 @@ const getLangDetail = (name) => {
}
.detail-section li {
padding: 0.5rem 0;
padding: 0.25rem 0;
font-size: 0.85rem;
color: var(--vp-c-text-2);
font-size: 0.9rem;
line-height: 1.5;
line-height: 1.4;
position: relative;
padding-left: 1.5rem;
padding-left: 1rem;
}
.detail-section li::before {
@@ -648,43 +396,27 @@ const getLangDetail = (name) => {
font-weight: bold;
}
.pros-cons {
display: flex;
flex-direction: column;
gap: 1rem;
}
.pros,
.cons {
font-size: 0.9rem;
}
.pros strong {
color: #10b981;
}
.cons strong {
color: #ef4444;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
transition: opacity 0.2s ease, transform 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(-10px);
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
}
.info-box .icon {
margin-right: 0.25rem;
}
</style>
@@ -1,11 +1,16 @@
<template>
<div class="concurrency-model-demo">
<div class="demo-header">
<h4>并发模型对比</h4>
<p class="subtitle">不同语言处理并发请求的方式</p>
<span class="icon">🔄</span>
<span class="title">并发模型</span>
<span class="subtitle">不同语言处理多任务的方式</span>
</div>
<div class="model-grid">
<div class="intro-text">
想象你在<span class="highlight">餐厅工作</span>有的餐厅多个服务员同时服务多线程有的只有一个服务员但动作极快事件循环有的像流水线一样分工协作协程
</div>
<div class="models-grid">
<div
v-for="model in models"
:key="model.name"
@@ -14,84 +19,63 @@
@click="selectedModel = model.name"
>
<div class="model-icon">{{ model.icon }}</div>
<h5>{{ model.name }}</h5>
<div class="model-tag">{{ model.tag }}</div>
<div class="model-name">{{ model.name }}</div>
<div class="model-lang">{{ model.language }}</div>
<div class="model-desc">{{ model.description }}</div>
</div>
</div>
<transition name="fade" mode="out-in">
<div :key="selectedModel" class="model-detail">
<Transition name="fade" mode="out-in">
<div v-if="selectedModel" :key="selectedModel" class="model-detail">
<div class="detail-header">
<h5>{{ getModelDetail(selectedModel).title }}</h5>
<div class="model-stats">
<div class="stat">
<span class="stat-label">并发能力</span>
<div class="stat-bar">
<div
class="stat-fill"
:style="{
width: getModelDetail(selectedModel).concurrency + '%'
}"
></div>
</div>
<h6>{{ getModelInfo().title }}</h6>
</div>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">并发能力</span>
<div class="stat-bar">
<div class="stat-fill" :style="{ width: getModelInfo().concurrency + '%' }"></div>
</div>
<div class="stat">
<span class="stat-label">内存开销</span>
<div class="stat-bar">
<div
class="stat-fill memory"
:style="{ width: getModelDetail(selectedModel).memory + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">CPU 利用率</span>
<div class="stat-bar">
<div
class="stat-fill cpu"
:style="{ width: getModelDetail(selectedModel).cpu + '%' }"
></div>
</div>
</div>
<div class="stat-item">
<span class="stat-label">内存开销</span>
<div class="stat-bar">
<div class="stat-fill memory" :style="{ width: getModelInfo().memory + '%' }"></div>
</div>
</div>
</div>
<div class="code-example">
<h6>代码示例</h6>
<pre><code>{{ getModelDetail(selectedModel).code }}</code></pre>
</div>
<div class="visualization">
<h6>并发可视化</h6>
<ConcurrencyVisualization :model="selectedModel" />
<code>{{ getModelInfo().code }}</code>
</div>
<div class="pros-cons">
<div class="pros">
<h6>优势</h6>
<strong> 优势</strong>
<ul>
<li v-for="pro in getModelDetail(selectedModel).pros" :key="pro">
{{ pro }}
</li>
<li v-for="pro in getModelInfo().pros" :key="pro">{{ pro }}</li>
</ul>
</div>
<div class="cons">
<h6>劣势</h6>
<strong> 劣势</strong>
<ul>
<li v-for="con in getModelDetail(selectedModel).cons" :key="con">
{{ con }}
</li>
<li v-for="con in getModelInfo().cons" :key="con">{{ con }}</li>
</ul>
</div>
</div>
</div>
</transition>
</Transition>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>Go 的协程适合高并发 I/OJava 的线程池适合稳定的企业级应用Node.js 的事件循环适合简单的 I/O 密集型任务根据场景选择而不是盲目追求"并发数"
</div>
</div>
</template>
<script setup>
import { ref, defineComponent } from 'vue'
import { ref } from 'vue'
const selectedModel = ref('Goroutine')
@@ -99,624 +83,244 @@ const models = [
{
name: 'Goroutine',
icon: '🐹',
tag: 'Go',
description: '轻量级协程,百万级并发'
language: 'Go',
description: '轻量级协程'
},
{
name: 'Thread',
name: 'Thread Pool',
icon: '🧵',
tag: 'Java',
description: '传统线程池,成熟稳定'
language: 'Java',
description: '线程池'
},
{
name: 'Async/Await',
name: 'Event Loop',
icon: '⚡',
tag: 'Node.js',
description: '事件循环,非阻塞 I/O'
language: 'Node.js',
description: '事件循环'
},
{
name: 'Async/Await',
icon: '🦀',
tag: 'Rust',
description: '零成本抽象,高性能'
language: 'Rust',
description: '异步运行时'
}
]
const modelDetails = {
const modelInfo = {
Goroutine: {
title: 'Go Goroutine (协程)',
concurrency: 95,
memory: 90,
cpu: 85,
code: `// Go: 启动 10 万个协程
package main
import (
"fmt"
"time"
)
func task(id int) {
fmt.Printf("Task %d\\n", id)
}
func main() {
for i := 0; i < 100000; i++ {
go task(i) // 启动协程
}
time.Sleep(time.Second)
}`,
pros: [
'✅ 轻量级:每个协程仅 2KB 栈内存',
'✅ 可创建百万级协程',
'✅ 语法简洁(go 关键字)',
'✅ 通信顺序进程(CSP)模型'
],
cons: [
'❌ 需要手动管理协程生命周期',
'❌ 错误处理繁琐(if err != nil',
'❌ 不如线程模型成熟'
]
code: 'go func() { /* 任务 */ }()',
pros: ['轻量级(2KB 栈内存)', '可创建百万级协程', '语法简洁'],
cons: ['需要手动管理生命周期', '错误处理繁琐']
},
Thread: {
title: 'Java Thread (线程池)',
'Thread Pool': {
title: 'Java Thread Pool (线程池)',
concurrency: 70,
memory: 40,
cpu: 80,
code: `// Java: 线程池处理并发
import java.util.concurrent.*;
ExecutorService executor =
Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId);
});
}
executor.shutdown();`,
pros: [
'✅ 成熟稳定,企业级应用首选',
'✅ 异常处理机制完善',
'✅ 调试工具丰富(JConsole、VisualVM',
'✅ 线程池优化(ExecutorService'
],
cons: [
'❌ 线程重(1-2MB 栈内存)',
'❌ 上下文切换开销大',
'❌ 并发数受限(通常 < 10000',
'❌ 锁竞争复杂'
]
code: 'executor.submit(() -> { /* 任务 */ });',
pros: ['成熟稳定', '异常处理完善', '工具丰富'],
cons: ['线程重(1-2MB 栈)', '上下文切换开销大']
},
'Async/Await': {
title: 'Node.js Async/Await (事件循环)',
'Event Loop': {
title: 'Node.js Event Loop (事件循环)',
concurrency: 85,
memory: 75,
cpu: 60,
code: `// Node.js: 异步处理
const axios = require('axios');
async function fetch(id) {
const response = await axios.get(url);
console.log(\`Task \${id}\`);
}
async function main() {
const tasks = [];
for (let i = 0; i < 10000; i++) {
tasks.push(fetch(i));
}
await Promise.all(tasks);
}
main();`,
pros: [
'✅ 适合 I/O 密集型应用',
'✅ 单线程,无锁竞争',
'✅ 事件驱动,非阻塞',
'✅ 语法优雅(async/await'
],
cons: [
'❌ 单线程,CPU 密集型性能差',
'❌ 回调地狱(虽然 async/await 有改善)',
'❌ 无法利用多核 CPU(需要 Worker Threads',
'❌ 错误堆栈复杂'
]
code: 'async function task() { /* 任务 */ }',
pros: ['适合 I/O 密集型', '单线程无锁竞争', '语法优雅'],
cons: ['CPU 密集型性能差', '无法利用多核']
},
RustAsync: {
'Async/Await': {
title: 'Rust Async/Await (零成本抽象)',
concurrency: 90,
memory: 95,
cpu: 90,
code: `// Rust: 异步运行时(tokio
use tokio::task;
async fn task(id: u32) {
println!("Task {}", id);
}
#[tokio::main]
async fn main() {
let mut handles = vec![];
for i in 0..100_000 {
let handle = task::spawn(async move {
task(i).await;
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
}`,
pros: [
'✅ 零成本抽象(编译成状态机)',
'✅ 内存安全(编译时保证)',
'✅ 性能接近手动管理',
'✅ 无 GC,无运行时开销'
],
cons: [
'❌ 学习曲线极其陡峭',
'❌ 需要运行时(tokio、async-std',
'❌ 编译时间长',
'❌ 生态不如 Go/Node.js 成熟'
]
code: 'task::spawn(async move { /* 任务 */ });',
pros: ['零成本抽象', '内存安全', '性能接近手动管理'],
cons: ['学习曲线陡峭', '需要运行时']
}
}
const getModelDetail = (model) => {
if (model === 'Async/Await') {
return selectedModel.value === 'Node.js'
? modelDetails['Async/Await']
: modelDetails.RustAsync
}
return modelDetails[model] || modelDetails.Goroutine
}
// ConcurrencyVisualization component
const ConcurrencyVisualization = defineComponent({
name: 'ConcurrencyVisualization',
props: {
model: String
},
template: `
<div class="concurrency-viz">
<div class="viz-container">
<div class="task-queue">
<div class="queue-label">任务队列</div>
<div class="queue-items">
<div
v-for="i in 20"
:key="i"
class="queue-item"
:class="{ processing: i <= activeWorkers }"
>
Task {{ i }}
</div>
</div>
</div>
<div class="workers">
<div class="workers-label">{{ workersLabel }}</div>
<div class="worker-pool">
<div
v-for="i in maxWorkers"
:key="i"
class="worker"
:class="{ active: i <= activeWorkers }"
>
{{ i <= activeWorkers ? '⚡' : '💤' }}
</div>
</div>
</div>
</div>
</div>
`,
setup(props) {
const workersLabel = computed(() => {
const labels = {
Goroutine: 'Goroutines (可无限创建)',
Thread: 'Thread Pool (固定数量)',
'Async/Await': 'Event Loop (单线程)',
RustAsync: 'Async Tasks (可无限创建)'
}
return labels[props.model] || 'Workers'
})
const maxWorkers = computed(() => {
const counts = {
Goroutine: 100,
Thread: 10,
'Async/Await': 1,
RustAsync: 100
}
return counts[props.model] || 10
})
const activeWorkers = computed(() => {
const actives = {
Goroutine: 100,
Thread: 10,
'Async/Await': 1,
RustAsync: 100
}
return actives[props.model] || 10
})
return {
workersLabel,
maxWorkers,
activeWorkers
}
}
})
</script>
<script>
import { computed, defineComponent } from 'vue'
export default {
components: {
ConcurrencyVisualization: defineComponent({
name: 'ConcurrencyVisualization',
props: {
model: String
},
template: `
<div class="concurrency-viz">
<div class="viz-container">
<div class="task-queue">
<div class="queue-label">任务队列</div>
<div class="queue-items">
<div
v-for="i in 20"
:key="i"
class="queue-item"
:class="{ processing: i <= activeWorkers }"
>
Task {{ i }}
</div>
</div>
</div>
<div class="workers">
<div class="workers-label">{{ workersLabel }}</div>
<div class="worker-pool">
<div
v-for="i in displayWorkers"
:key="i"
class="worker"
:class="{ active: i <= activeWorkers }"
>
{{ i <= activeWorkers ? '⚡' : '💤' }}
</div>
</div>
</div>
</div>
</div>
`,
setup(props) {
const workersLabel = computed(() => {
const labels = {
Goroutine: 'Goroutines (可无限创建)',
Thread: 'Thread Pool (固定数量)',
'Async/Await': 'Event Loop (单线程)',
RustAsync: 'Async Tasks (可无限创建)'
}
return labels[props.model] || 'Workers'
})
const maxWorkers = computed(() => {
const counts = {
Goroutine: 20,
Thread: 10,
'Async/Await': 1,
RustAsync: 20
}
return counts[props.model] || 10
})
const activeWorkers = computed(() => {
const actives = {
Goroutine: 20,
Thread: 10,
'Async/Await': 1,
RustAsync: 20
}
return actives[props.model] || 10
})
const displayWorkers = computed(() => {
// 限制显示数量,避免 DOM 过多
return Math.min(maxWorkers.value, 20)
})
return {
workersLabel,
maxWorkers,
activeWorkers,
displayWorkers
}
}
})
}
const getModelInfo = () => {
return modelInfo[selectedModel.value] || modelInfo.Goroutine
}
</script>
<style scoped>
.concurrency-model-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
max-height: 600px;
overflow-y: auto;
}
.demo-header {
text-align: center;
margin-bottom: 2rem;
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
.demo-header .icon {
font-size: 1.25rem;
}
.subtitle {
margin: 0;
.demo-header .title {
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
font-size: 0.95rem;
font-size: 0.85rem;
margin-left: 0.5rem;
}
.model-grid {
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.models-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 0.5rem;
margin-bottom: 1rem;
}
.model-card {
background: var(--vp-c-bg-soft);
background: var(--vp-c-bg);
padding: 0.75rem;
border: 2px solid transparent;
border-radius: 8px;
padding: 1.5rem;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
transition: all 0.2s ease;
text-align: center;
}
.model-card:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
border-color: var(--vp-c-brand);
}
.model-card.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg);
background: var(--vp-c-brand-soft);
}
.model-icon {
font-size: 3rem;
margin-bottom: 0.5rem;
font-size: 1.5rem;
margin-bottom: 0.25rem;
}
.model-card h5 {
margin: 0.5rem 0;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.model-tag {
display: inline-block;
padding: 0.25rem 0.75rem;
background: var(--vp-c-brand);
color: white;
border-radius: 12px;
font-size: 0.75rem;
.model-name {
font-weight: 600;
margin-bottom: 0.5rem;
font-size: 0.85rem;
color: var(--vp-c-text-1);
}
.model-lang {
font-size: 0.7rem;
color: var(--vp-c-brand-1);
margin-bottom: 0.25rem;
}
.model-desc {
font-size: 0.85rem;
font-size: 0.7rem;
color: var(--vp-c-text-2);
line-height: 1.4;
}
.model-detail {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 2rem;
animation: fade-in 0.3s ease;
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
}
.detail-header {
margin-bottom: 2rem;
.detail-header h6 {
margin: 0 0 0.75rem 0;
font-size: 0.9rem;
color: var(--vp-c-text-1);
}
.detail-header h5 {
margin: 0 0 1.5rem 0;
color: var(--vp-c-brand);
font-size: 1.3rem;
}
.model-stats {
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
grid-template-columns: 1fr 1fr;
gap: 0.75rem;
margin-bottom: 0.75rem;
}
.stat {
.stat-item {
display: flex;
flex-direction: column;
gap: 0.5rem;
gap: 0.25rem;
}
.stat-label {
font-size: 0.85rem;
font-size: 0.75rem;
font-weight: 600;
color: var(--vp-c-text-1);
}
.stat-bar {
height: 8px;
background: var(--vp-c-bg);
border-radius: 4px;
height: 6px;
background: var(--vp-c-bg-soft);
border-radius: 3px;
overflow: hidden;
}
.stat-fill {
height: 100%;
background: linear-gradient(90deg, var(--vp-c-brand), #8b5cf6);
background: var(--vp-c-brand);
transition: width 0.5s ease;
}
.stat-fill.memory {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.stat-fill.cpu {
background: linear-gradient(90deg, #10b981, #059669);
background: var(--vp-c-green-1);
}
.code-example {
background: #1e1e1e;
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 2rem;
overflow-x: auto;
}
.code-example h6 {
margin: 0 0 1rem 0;
color: #4ec9b0;
font-size: 1rem;
}
.code-example pre {
margin: 0;
padding: 0.5rem;
border-radius: 4px;
margin-bottom: 0.75rem;
}
.code-example code {
color: #4ec9b0;
font-family: 'Monaco', 'Menlo', monospace;
font-size: 0.85rem;
line-height: 1.6;
color: #d4d4d4;
}
.visualization {
margin-bottom: 2rem;
}
.visualization h6 {
margin: 0 0 1rem 0;
color: var(--vp-c-text-1);
font-size: 1rem;
}
.concurrency-viz {
background: var(--vp-c-bg);
border-radius: 8px;
padding: 1.5rem;
border: 1px solid var(--vp-c-divider);
}
.viz-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
.task-queue,
.workers {
display: flex;
flex-direction: column;
gap: 1rem;
}
.queue-label,
.workers-label {
font-weight: 600;
color: var(--vp-c-text-1);
font-size: 0.9rem;
}
.queue-items {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.queue-item {
padding: 0.5rem;
background: var(--vp-c-bg-soft);
border-radius: 4px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
transition: all 0.3s ease;
}
.queue-item.processing {
background: #dcfce7;
color: #15803d;
font-weight: 600;
}
.worker-pool {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.worker {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-bg-soft);
border-radius: 8px;
font-size: 1.2rem;
transition: all 0.3s ease;
}
.worker.active {
background: #dcfce7;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
font-size: 0.75rem;
}
.pros-cons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
gap: 0.75rem;
}
.pros h6,
.cons h6 {
margin: 0 0 1rem 0;
font-size: 1rem;
.pros strong {
display: block;
margin-bottom: 0.25rem;
font-size: 0.8rem;
color: var(--vp-c-green-1);
}
.pros h6 {
color: #10b981;
}
.cons h6 {
color: #ef4444;
.cons strong {
display: block;
margin-bottom: 0.25rem;
font-size: 0.8rem;
color: var(--vp-c-red-1);
}
.pros ul,
@@ -728,15 +332,15 @@ export default {
.pros li,
.cons li {
padding: 0.5rem 0;
font-size: 0.9rem;
padding: 0.15rem 0;
font-size: 0.75rem;
color: var(--vp-c-text-2);
line-height: 1.5;
line-height: 1.3;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
transition: opacity 0.2s ease;
}
.fade-enter-from,
@@ -744,28 +348,16 @@ export default {
opacity: 0;
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
}
@media (max-width: 768px) {
.model-stats {
grid-template-columns: 1fr;
}
.viz-container {
grid-template-columns: 1fr;
}
.pros-cons {
grid-template-columns: 1fr;
}
.info-box .icon {
margin-right: 0.25rem;
}
</style>
@@ -1,144 +1,50 @@
<template>
<div class="developer-efficiency-demo">
<div class="demo-header">
<h4>开发效率对比</h4>
<p class="subtitle">不同语言完成相同任务所需的代码量和时间</p>
<span class="icon"></span>
<span class="title">开发效率</span>
<span class="subtitle">不同语言完成相同任务的时间成本</span>
</div>
<div class="intro-text">
想象你在<span class="highlight">装修房子</span>有的装修队能快速完工但质量一般PythonRuby有的慢工出细活RustC++有的速度和质量都不错GoNode.js
</div>
<div class="task-selector">
<label>选择任务</label>
<select v-model="selectedTask" @change="updateMetrics">
<option v-for="task in tasks" :key="task.id" :value="task.id">
{{ task.name }}
</option>
<select v-model="selectedTask">
<option value="rest">REST API</option>
<option value="web">Web 应用</option>
<option value="script">数据处理脚本</option>
</select>
</div>
<div class="metrics-grid">
<div class="metric-card">
<div class="metric-header">
<span class="metric-icon">📝</span>
<h5>代码行数</h5>
</div>
<div class="metric-chart">
<div
v-for="lang in sortedLanguages"
:key="lang.name"
class="metric-bar"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-container">
<div
class="bar-fill"
:style="{ width: getBarWidth(lang.lines) + '%' }"
>
<span class="bar-value">{{ lang.lines }}</span>
</div>
</div>
</div>
</div>
<div class="metric-insight">
<p>
<strong>💡 分析</strong>
{{ getTaskDetail(selectedTask).linesInsight }}
</p>
</div>
<div class="efficiency-chart">
<div class="chart-header">
<span>开发时间小时</span>
</div>
<div class="metric-card">
<div class="metric-header">
<span class="metric-icon"></span>
<h5>开发时间小时</h5>
</div>
<div class="metric-chart">
<div
v-for="lang in sortedLanguages"
:key="lang.name"
class="metric-bar"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-container">
<div
class="bar-fill time"
:style="{ width: getBarWidth(lang.time) + '%' }"
>
<span class="bar-value">{{ lang.time }}h</span>
</div>
<div class="bars">
<div
v-for="lang in sortedLanguages"
:key="lang.name"
class="bar-wrapper"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-track">
<div
class="bar-fill"
:style="{ width: (lang.time / maxTime * 100) + '%' }"
>
<span class="bar-value">{{ lang.time }}h</span>
</div>
</div>
</div>
<div class="metric-insight">
<p>
<strong>💡 分析</strong>
{{ getTaskDetail(selectedTask).timeInsight }}
</p>
</div>
</div>
<div class="metric-card">
<div class="metric-header">
<span class="metric-icon">🐛</span>
<h5>调试时间小时</h5>
</div>
<div class="metric-chart">
<div
v-for="lang in sortedLanguages"
:key="lang.name"
class="metric-bar"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-container">
<div
class="bar-fill debug"
:style="{ width: getBarWidth(lang.debug) + '%' }"
>
<span class="bar-value">{{ lang.debug }}h</span>
</div>
</div>
</div>
</div>
<div class="metric-insight">
<p>
<strong>💡 分析</strong>
{{ getTaskDetail(selectedTask).debugInsight }}
</p>
</div>
</div>
</div>
<div class="efficiency-radar">
<h5>综合效率雷达图</h5>
<div class="radar-chart">
<div class="radar-grid">
<div
v-for="lang in languages"
:key="lang.name"
class="radar-point"
:style="getRadarPosition(lang)"
>
<div class="point-label">{{ lang.name }}</div>
<div class="point-dot"></div>
</div>
</div>
</div>
<div class="radar-legend">
<div class="legend-item">
<span class="legend-dot"></span>
<span>左上代码少开发快</span>
</div>
<div class="legend-item">
<span class="legend-dot"></span>
<span>右上调试快类型安全</span>
</div>
<div class="legend-item">
<span class="legend-dot"></span>
<span>左下生态好库丰富</span>
</div>
<div class="legend-item">
<span class="legend-dot"></span>
<span>右下学习简单上手快</span>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>初创公司选 Python/Ruby 快速验证想法大厂选 Java/Go 平衡速度和质量开发效率不只是写代码的速度还包括调试测试维护的时间成本
</div>
</div>
</template>
@@ -148,259 +54,153 @@ import { ref, computed } from 'vue'
const selectedTask = ref('rest')
const tasks = [
{ id: 'rest', name: 'REST API 服务' },
{ id: 'web', name: 'Web 应用' },
{ id: 'script', name: '数据处理脚本' },
{ id: 'micro', name: '微服务' }
]
const languages = [
'Python',
'Ruby',
'Go',
'Node.js',
'Java',
'C#',
'Rust',
'C++'
]
const taskMetrics = {
rest: {
Python: { lines: 50, time: 4, debug: 2 },
Ruby: { lines: 45, time: 3.5, debug: 2.5 },
Go: { lines: 80, time: 5, debug: 1.5 },
'Node.js': { lines: 60, time: 4.5, debug: 2 },
Java: { lines: 150, time: 8, debug: 2 },
'C#': { lines: 120, time: 7, debug: 2 },
Rust: { lines: 100, time: 10, debug: 3 },
'C++': { lines: 180, time: 12, debug: 5 },
linesInsight:
'Python 和 Ruby 用最少的代码实现 REST API,得益于简洁的语法和强大的框架(Flask、Sinatra)。Go 虽然语法简洁,但需要显式类型声明。Java 和 C# 的样板代码最多。',
timeInsight:
'Ruby 和 Python 开发最快,适合快速迭代。Go 和 Node.js 居中,平衡了开发速度和性能。Java 和 C# 开发时间较长,但后期维护成本低。Rust 和 C++ 开发时间最长,主要受学习曲线和编译时间影响。',
debugInsight:
'Go、Java、C# 的静态类型让调试更容易,大部分错误在编译时就能发现。Python 和 Ruby 虽然开发快,但运行时错误多,调试时间长。Rust 的借用检查器虽然学习曲线陡峭,但能提前发现大量 bug。'
},
web: {
Python: { lines: 200, time: 10, debug: 5 },
Ruby: { lines: 180, time: 9, debug: 5 },
Go: { lines: 300, time: 12, debug: 4 },
'Node.js': { lines: 250, time: 11, debug: 5 },
Java: { lines: 500, time: 20, debug: 6 },
'C#': { lines: 400, time: 18, debug: 6 },
Rust: { lines: 350, time: 25, debug: 8 },
'C++': { lines: 600, time: 30, debug: 12 },
linesInsight:
'Rails 和 Django 的"约定优于配置"让 Web 开发极其高效,代码量最少。全栈的 Node.js 也表现不错。Go 需要 more boilerplate。Java 的 Spring Boot 虽然强大,但配置和样板代码较多。',
timeInsight:
'Ruby (Rails) 和 Python (Django) 是 Web 开发的效率之王,内置 ORM、模板引擎、认证等功能,开箱即用。Node.js 的全栈特性让前后端统一,减少沟通成本。Go 和 Java 需要更多配置和 boilerplate。',
debugInsight:
'静态类型语言(Go、Java、C#)在大型 Web 项目中优势明显,IDE 支持更好,重构更安全。Python 和 Ruby 在小项目中调试很快,但随着项目增长,动态类型带来的维护成本会急剧上升。'
},
script: {
Python: { lines: 20, time: 1, debug: 0.5 },
Ruby: { lines: 18, time: 1, debug: 0.5 },
Go: { lines: 40, time: 2, debug: 0.5 },
'Node.js': { lines: 25, time: 1.5, debug: 0.5 },
Java: { lines: 80, time: 4, debug: 1 },
'C#': { lines: 70, time: 3.5, debug: 1 },
Rust: { lines: 50, time: 4, debug: 1 },
'C++': { lines: 100, time: 5, debug: 2 },
linesInsight:
'Python 是脚本自动化的绝对王者,标准库丰富,第三方库如 Pandas、Requests 让数据处理极其简单。Ruby 也很优秀。其他语言对于简单脚本来说都太重量级了。',
timeInsight:
'Python 和 Ruby 是脚本任务的首选,几行代码就能完成复杂的数据处理。Node.js 在处理 JSON 数据时也很方便。编译型语言(Go、Java、C++)对于简单脚本来说 overhead 太大。',
debugInsight:
'Python 的交互式解释器(REPL)和丰富的调试工具(pdb、ipdb)让脚本调试极其高效。Ruby 的 Pry 也很强大。其他语言的编译/运行循环对于脚本开发来说太慢了。'
},
micro: {
Python: { lines: 100, time: 6, debug: 3 },
Ruby: { lines: 90, time: 5.5, debug: 3.5 },
Go: { lines: 120, time: 7, debug: 2 },
'Node.js': { lines: 110, time: 6.5, debug: 3 },
Java: { lines: 250, time: 15, debug: 4 },
'C#': { lines: 200, time: 13, debug: 4 },
Rust: { lines: 140, time: 18, debug: 5 },
'C++': { lines: 300, time: 22, debug: 8 },
linesInsight:
'Go 是微服务的理想选择,单一二进制文件 + 内置 HTTP 服务器 + 强大的标准库。Node.js 的 Express/Koa 也很轻量。Python 的 FastAPI 表现不错,但性能和并发不如 Go。',
timeInsight:
'Go 和 Node.js 在微服务开发中效率最高,启动快,部署简单。Python 和 Ruby 适合快速原型,但生产环境需要更多优化。Java 和 C# 的 Spring Cloud/.NET 虽然强大,但对于简单微服务来说太重量级。',
debugInsight:
'Go 和 Rust 的类型系统和错误处理让微服务的调试和测试更容易。Java 和 C# 的成熟工具链(JUnit、NUnit)也很有优势。Python 和 Ruby 的动态类型在分布式系统中可能带来运行时错误。'
}
const taskData = {
rest: [
{ name: 'Python', time: 4 },
{ name: 'Ruby', time: 3.5 },
{ name: 'Go', time: 5 },
{ name: 'Node.js', time: 4.5 },
{ name: 'Java', time: 8 },
{ name: 'Rust', time: 10 }
],
web: [
{ name: 'Ruby', time: 9 },
{ name: 'Python', time: 10 },
{ name: 'Node.js', time: 11 },
{ name: 'Go', time: 12 },
{ name: 'Java', time: 20 },
{ name: 'Rust', time: 25 }
],
script: [
{ name: 'Python', time: 1 },
{ name: 'Ruby', time: 1 },
{ name: 'Node.js', time: 1.5 },
{ name: 'Go', time: 2 },
{ name: 'Java', time: 4 },
{ name: 'Rust', time: 4 }
]
}
const currentMetrics = computed(() => {
return taskMetrics[selectedTask.value]
})
const sortedLanguages = computed(() => {
return languages
.map((lang) => ({
name: lang,
...currentMetrics.value[lang]
}))
.sort((a, b) => a.lines - b.lines)
return [...taskData[selectedTask.value]].sort((a, b) => a.time - b.time)
})
const getBarWidth = (value) => {
const max = Math.max(
...Object.values(currentMetrics.value).flatMap((v) => [
v.lines,
v.time * 20,
v.debug * 20
])
)
return (value / max) * 100
}
const getTaskDetail = (taskId) => {
return taskMetrics[taskId]
}
const getRadarPosition = (langName) => {
const metrics = currentMetrics.value[langName]
const avgLines =
Object.values(currentMetrics.value).reduce((sum, v) => sum + v.lines, 0) /
languages.length
const avgTime =
Object.values(currentMetrics.value).reduce((sum, v) => sum + v.time, 0) /
languages.length
const avgDebug =
Object.values(currentMetrics.value).reduce((sum, v) => sum + v.debug, 0) /
languages.length
// Normalize metrics (lower is better, so we invert)
const linesScore = 1 - metrics.lines / 300 // Max lines ~300
const timeScore = 1 - metrics.time / 30 // Max time ~30
const debugScore = 1 - metrics.debug / 12 // Max debug ~12
// Position in 2D space
// X: code efficiency (linesScore) vs ecosystem (hardcoded)
// Y: speed (timeScore) vs maintainability (debugScore)
const x = 50 + (linesScore - 0.5) * 80
const y = 50 + (timeScore - 0.5) * 80
return {
left: `${x}%`,
top: `${y}%`
}
}
const updateMetrics = () => {
// Trigger reactivity
}
const maxTime = computed(() => {
return Math.max(...taskData[selectedTask.value].map(l => l.time))
})
</script>
<style scoped>
.developer-efficiency-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
max-height: 600px;
overflow-y: auto;
}
.demo-header {
text-align: center;
margin-bottom: 2rem;
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
.demo-header .icon {
font-size: 1.25rem;
}
.subtitle {
margin: 0;
.demo-header .title {
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
font-size: 0.95rem;
font-size: 0.85rem;
margin-left: 0.5rem;
}
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.task-selector {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin-bottom: 2rem;
flex-wrap: wrap;
gap: 0.5rem;
margin-bottom: 1rem;
background: var(--vp-c-bg);
padding: 0.5rem 0.75rem;
border-radius: 6px;
}
.task-selector label {
font-size: 0.85rem;
font-weight: 600;
color: var(--vp-c-text-1);
}
.task-selector select {
padding: 0.5rem 1rem;
padding: 0.35rem 0.5rem;
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
background: var(--vp-c-bg);
border-radius: 4px;
background: var(--vp-c-bg-alt);
color: var(--vp-c-text-1);
font-size: 0.9rem;
font-size: 0.85rem;
cursor: pointer;
}
.metrics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 3rem;
.efficiency-chart {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.metric-card {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 1.5rem;
border: 1px solid var(--vp-c-divider);
}
.metric-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1.5rem;
}
.metric-icon {
font-size: 2rem;
}
.metric-header h5 {
margin: 0;
.chart-header {
margin-bottom: 0.75rem;
font-size: 0.85rem;
font-weight: 600;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.metric-chart {
.bars {
display: flex;
flex-direction: column;
gap: 0.75rem;
margin-bottom: 1.5rem;
gap: 0.5rem;
}
.metric-bar {
.bar-wrapper {
display: flex;
align-items: center;
gap: 1rem;
gap: 0.5rem;
}
.bar-label {
min-width: 70px;
font-size: 0.8rem;
font-weight: 600;
font-size: 0.85rem;
color: var(--vp-c-text-1);
}
.bar-container {
.bar-track {
flex: 1;
height: 24px;
background: var(--vp-c-bg);
background: var(--vp-c-bg-soft);
border-radius: 4px;
overflow: hidden;
}
@@ -411,134 +211,22 @@ const updateMetrics = () => {
align-items: center;
justify-content: flex-end;
padding-right: 0.5rem;
background: linear-gradient(90deg, var(--vp-c-brand), #8b5cf6);
background: var(--vp-c-green-1);
transition: width 0.5s ease;
color: white;
font-weight: 600;
font-size: 0.75rem;
}
.bar-fill.time {
background: linear-gradient(90deg, #10b981, #059669);
}
.bar-fill.debug {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.metric-insight {
background: var(--vp-c-bg);
border-radius: 8px;
padding: 1rem;
border-left: 3px solid var(--vp-c-brand);
}
.metric-insight p {
margin: 0;
font-size: 0.85rem;
line-height: 1.6;
color: var(--vp-c-text-2);
}
.efficiency-radar {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 2rem;
border: 1px solid var(--vp-c-divider);
}
.efficiency-radar h5 {
margin: 0 0 2rem 0;
text-align: center;
color: var(--vp-c-text-1);
font-size: 1.2rem;
}
.radar-chart {
position: relative;
width: 100%;
height: 400px;
background: var(--vp-c-bg);
border-radius: 8px;
margin-bottom: 1.5rem;
}
.radar-grid {
position: relative;
width: 100%;
height: 100%;
}
.radar-point {
position: absolute;
transform: translate(-50%, -50%);
cursor: pointer;
transition: all 0.3s ease;
}
.radar-point:hover {
transform: translate(-50%, -50%) scale(1.2);
}
.point-label {
position: absolute;
top: -25px;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
font-weight: 600;
font-size: 0.85rem;
color: var(--vp-c-text-1);
background: var(--vp-c-bg-soft);
padding: 0.25rem 0.5rem;
border-radius: 4px;
}
.point-dot {
width: 12px;
height: 12px;
background: var(--vp-c-brand);
border-radius: 50%;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.5);
}
.radar-legend {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.5rem;
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.legend-dot {
width: 10px;
height: 10px;
background: var(--vp-c-brand);
border-radius: 50%;
}
@media (max-width: 768px) {
.metrics-grid {
grid-template-columns: 1fr;
}
.bar-label {
min-width: 55px;
font-size: 0.75rem;
}
.efficiency-radar {
padding: 1rem;
}
.radar-chart {
height: 300px;
}
.info-box .icon {
margin-right: 0.25rem;
}
</style>
@@ -1,202 +1,323 @@
<template>
<div class="language-comparison-demo">
<div class="comparison-table-wrapper">
<table class="comparison-table">
<thead>
<tr>
<th>维度</th>
<th v-for="lang in languages" :key="lang.name" class="lang-col">
{{ lang.name }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="dimension in dimensions" :key="dimension.key">
<td class="dimension-label">{{ dimension.label }}</td>
<td v-for="lang in languages" :key="lang.name" class="score-cell">
<div class="score-bar">
<div
class="score-fill"
:class="`score-${dimension.key}`"
:style="{ width: getScore(lang.name, dimension.key) + '%' }"
>
<span class="score-text">{{
getScore(lang.name, dimension.key)
}}</span>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div class="demo-header">
<span class="icon"></span>
<span class="title">语言天平</span>
<span class="subtitle">权衡不同维度的优劣势</span>
</div>
<div class="insight-panel">
<h4>💡 洞察分析</h4>
<div class="insight-content">
<div class="insight-item">
<strong>性能王者</strong>
<span>C++ Rust 在性能方面遥遥领先但学习曲线极其陡峭</span>
</div>
<div class="insight-item">
<strong>开发效率</strong>
<span
>Python Ruby 在快速开发方面无与伦比适合原型和初创公司</span
>
</div>
<div class="insight-item">
<strong>生态成熟度</strong>
<span
>JavaPythonNode.js 拥有最成熟的生态系统库和框架丰富</span
>
</div>
<div class="insight-item">
<strong>学习曲线</strong>
<span
>PythonRubyGo 最容易上手Rust C++ 需要较长时间学习</span
>
<div class="intro-text">
想象你在<span class="highlight">超市购物</span>有的商品便宜但不耐用有的质量好但价格高选择后端语言也一样需要在性能开发效率生态成熟度等多个维度之间做权衡
</div>
<div class="dimension-selector">
<div class="dimension-label">选择比较维度</div>
<div class="dimension-buttons">
<button
v-for="dim in dimensions"
:key="dim.key"
class="dimension-btn"
:class="{ active: selectedDimension === dim.key }"
@click="selectedDimension = dim.key"
>
<span class="dim-icon">{{ dim.icon }}</span>
<span class="dim-label">{{ dim.label }}</span>
</button>
</div>
</div>
<div class="comparison-chart">
<div class="chart-header">
<span class="chart-title">{{ getDimensionInfo().title }}</span>
<span class="chart-unit">{{ getDimensionInfo().unit }}</span>
</div>
<div class="bars-container">
<div
v-for="lang in sortedLanguages"
:key="lang.name"
class="bar-wrapper"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-track">
<div
class="bar-fill"
:class="getBarClass(lang.score)"
:style="{ width: lang.score + '%' }"
>
<span class="bar-value">{{ lang.score }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="insight-box">
<span class="icon">🔍</span>
<div class="insight-content">
<strong>洞察分析</strong>
<p>{{ getDimensionInfo().insight }}</p>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>没有"万能银弹"高性能往往意味着高开发成本C++Rust快速开发通常伴随性能损失PythonRuby根据项目核心诉求做取舍而不是追求"样样都行"
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ref, computed } from 'vue'
const languages = [
{ name: 'Java' },
{ name: 'Python' },
{ name: 'Go' },
{ name: 'Node.js' },
{ name: 'Rust' },
{ name: 'C++' }
]
const selectedDimension = ref('performance')
const dimensions = [
{ key: 'performance', label: '性能' },
{ key: 'efficiency', label: '开发效率' },
{ key: 'ecosystem', label: '生态成熟度' },
{ key: 'learning', label: '学习曲线' },
{ key: 'concurrency', label: '并发能力' },
{ key: 'memory', label: '内存管理' }
{ key: 'performance', icon: '⚡', label: '性能' },
{ key: 'efficiency', icon: '🚀', label: '开发效率' },
{ key: 'ecosystem', icon: '📦', label: '生态成熟度' },
{ key: 'learning', icon: '📚', label: '学习曲线' },
{ key: 'concurrency', icon: '🔄', label: '并发能力' }
]
const scores = {
Java: {
performance: 75,
efficiency: 60,
ecosystem: 95,
learning: 40,
concurrency: 80,
memory: 70
const dimensionInfo = {
performance: {
title: '性能对比',
unit: '(分数越高越快)',
insight: 'C++ 和 Rust 在性能方面遥遥领先,但学习曲线极其陡峭。Go 和 Java 在性能和开发效率之间取得了很好的平衡。Python 和 Ruby 性能最弱,但开发速度最快。'
},
Python: {
performance: 30,
efficiency: 95,
ecosystem: 95,
learning: 95,
concurrency: 30,
memory: 40
efficiency: {
title: '开发效率',
unit: '(分数越高越快)',
insight: 'Python 和 Ruby 在快速开发方面无与伦比,适合原型和初创公司。Go 和 Node.js 居中,兼顾了开发速度和性能。Rust 和 C++ 开发效率最低,主要受学习曲线影响。'
},
Go: {
performance: 90,
efficiency: 85,
ecosystem: 75,
learning: 80,
concurrency: 95,
memory: 85
ecosystem: {
title: '生态成熟度',
unit: '(分数越高库越多)',
insight: 'Java、Python、Node.js 拥有最成熟的生态系统。Go 和 Rust 虽然年轻,但发展迅速。C++ 生态成熟但学习成本高。Ruby 生态主要集中在 Web 开发领域。'
},
'Node.js': {
performance: 70,
efficiency: 85,
ecosystem: 95,
learning: 75,
concurrency: 85,
memory: 75
learning: {
title: '学习曲线',
unit: '(分数越高越简单)',
insight: 'Python、Ruby、Go 最容易上手。Node.js 需要理解异步概念。Java 需要掌握面向对象和框架。Rust 和 C++ 学习曲线最陡,需要深入理解内存管理。'
},
Rust: {
performance: 95,
efficiency: 40,
ecosystem: 70,
learning: 20,
concurrency: 90,
memory: 98
},
'C++': {
performance: 98,
efficiency: 35,
ecosystem: 90,
learning: 25,
concurrency: 85,
memory: 70
concurrency: {
title: '并发能力',
unit: '(分数越高越强)',
insight: 'Go 的 Goroutine 是并发的王者,轻量且简单。Rust 的异步模型性能强大但复杂。Java 的线程池成熟稳定。Node.js 的事件循环适合 I/O 密集型。Python 的 GIL 限制了多线程性能。'
}
}
const getScore = (lang, dimension) => {
return scores[lang][dimension]
const languageScores = {
performance: [
{ name: 'C++', score: 98 },
{ name: 'Rust', score: 95 },
{ name: 'Go', score: 90 },
{ name: 'Java', score: 75 },
{ name: 'Node.js', score: 70 },
{ name: 'Python', score: 30 },
{ name: 'Ruby', score: 25 }
],
efficiency: [
{ name: 'Python', score: 95 },
{ name: 'Ruby', score: 90 },
{ name: 'Go', score: 85 },
{ name: 'Node.js', score: 85 },
{ name: 'Java', score: 60 },
{ name: 'Rust', score: 40 },
{ name: 'C++', score: 35 }
],
ecosystem: [
{ name: 'Java', score: 95 },
{ name: 'Python', score: 95 },
{ name: 'Node.js', score: 95 },
{ name: 'C++', score: 90 },
{ name: 'Go', score: 75 },
{ name: 'Ruby', score: 70 },
{ name: 'Rust', score: 70 }
],
learning: [
{ name: 'Python', score: 95 },
{ name: 'Ruby', score: 85 },
{ name: 'Go', score: 80 },
{ name: 'Node.js', score: 75 },
{ name: 'Java', score: 40 },
{ name: 'C++', score: 25 },
{ name: 'Rust', score: 20 }
],
concurrency: [
{ name: 'Go', score: 95 },
{ name: 'Rust', score: 90 },
{ name: 'Node.js', score: 85 },
{ name: 'Java', score: 80 },
{ name: 'C++', score: 85 },
{ name: 'Python', score: 30 },
{ name: 'Ruby', score: 25 }
]
}
const sortedLanguages = computed(() => {
const scores = languageScores[selectedDimension.value]
return [...scores].sort((a, b) => b.score - a.score)
})
const getDimensionInfo = () => {
return dimensionInfo[selectedDimension.value]
}
const getBarClass = (score) => {
if (score >= 85) return 'bar-high'
if (score >= 60) return 'bar-medium'
return 'bar-low'
}
</script>
<style scoped>
.language-comparison-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
}
.comparison-table-wrapper {
overflow-x: auto;
margin-bottom: 2rem;
}
.comparison-table {
width: 100%;
border-collapse: collapse;
min-width: 600px;
}
.comparison-table th {
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
text-align: center;
font-weight: 600;
color: var(--vp-c-text-1);
border-bottom: 2px solid var(--vp-c-divider);
margin: 1rem 0;
max-height: 600px;
overflow-y: auto;
}
.comparison-table th.lang-col {
color: var(--vp-c-brand);
font-size: 1.1rem;
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.comparison-table td {
padding: 1rem;
border-bottom: 1px solid var(--vp-c-divider);
.demo-header .icon {
font-size: 1.25rem;
}
.demo-header .title {
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
font-size: 0.85rem;
margin-left: 0.5rem;
}
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.dimension-selector {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.dimension-label {
font-size: 0.85rem;
font-weight: 600;
color: var(--vp-c-text-1);
white-space: nowrap;
margin-bottom: 0.5rem;
}
.score-cell {
padding: 0.75rem;
.dimension-buttons {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.score-bar {
height: 30px;
.dimension-btn {
display: flex;
align-items: center;
gap: 0.25rem;
padding: 0.4rem 0.75rem;
background: var(--vp-c-bg-soft);
border: 2px solid transparent;
border-radius: 6px;
overflow: hidden;
position: relative;
cursor: pointer;
transition: all 0.2s ease;
font-size: 0.85rem;
}
.score-fill {
.dimension-btn:hover {
border-color: var(--vp-c-brand);
}
.dimension-btn.active {
background: var(--vp-c-brand);
color: white;
}
.dim-icon {
font-size: 1rem;
}
.comparison-chart {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
}
.chart-title {
font-weight: 600;
font-size: 0.9rem;
color: var(--vp-c-text-1);
}
.chart-unit {
font-size: 0.75rem;
color: var(--vp-c-text-3);
}
.bars-container {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.bar-wrapper {
display: flex;
align-items: center;
gap: 0.5rem;
}
.bar-label {
min-width: 70px;
font-size: 0.8rem;
font-weight: 600;
color: var(--vp-c-text-1);
}
.bar-track {
flex: 1;
height: 24px;
background: var(--vp-c-bg-soft);
border-radius: 4px;
overflow: hidden;
}
.bar-fill {
height: 100%;
display: flex;
align-items: center;
@@ -205,86 +326,62 @@ const getScore = (lang, dimension) => {
transition: width 0.5s ease;
color: white;
font-weight: 600;
font-size: 0.85rem;
font-size: 0.75rem;
}
.score-performance {
background: linear-gradient(90deg, #fbbf24, #f59e0b);
.bar-high {
background: var(--vp-c-green-1);
}
.score-efficiency {
background: linear-gradient(90deg, #34d399, #10b981);
.bar-medium {
background: var(--vp-c-yellow-1);
}
.score-ecosystem {
background: linear-gradient(90deg, #60a5fa, #3b82f6);
.bar-low {
background: var(--vp-c-brand-1);
}
.score-learning {
background: linear-gradient(90deg, #f472b6, #ec4899);
}
.score-concurrency {
background: linear-gradient(90deg, #a78bfa, #8b5cf6);
}
.score-memory {
background: linear-gradient(90deg, #fb923c, #ea580c);
}
.score-text {
color: white;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.insight-panel {
background: var(--vp-c-bg-soft);
border-radius: 8px;
padding: 1.5rem;
border-left: 4px solid var(--vp-c-brand);
}
.insight-panel h4 {
margin-top: 0;
.insight-box {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
color: var(--vp-c-brand);
font-size: 1.2rem;
display: flex;
gap: 0.5rem;
border-left: 3px solid var(--vp-c-brand);
}
.insight-box .icon {
flex-shrink: 0;
}
.insight-content {
display: flex;
flex-direction: column;
gap: 1rem;
flex: 1;
}
.insight-item {
display: flex;
gap: 0.5rem;
font-size: 0.95rem;
line-height: 1.6;
}
.insight-item strong {
.insight-content strong {
display: block;
margin-bottom: 0.25rem;
font-size: 0.85rem;
color: var(--vp-c-text-1);
white-space: nowrap;
}
.insight-item span {
.insight-content p {
margin: 0;
font-size: 0.85rem;
color: var(--vp-c-text-2);
line-height: 1.5;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
@media (max-width: 768px) {
.comparison-table-wrapper {
font-size: 0.85rem;
}
.comparison-table th,
.comparison-table td {
padding: 0.5rem;
}
.insight-content {
font-size: 0.9rem;
}
.info-box .icon {
margin-right: 0.25rem;
}
</style>
File diff suppressed because it is too large Load Diff
@@ -1,593 +1,370 @@
<template>
<div class="language-selector-demo">
<div class="selector-header">
<h4>🎯 语言选择器</h4>
<p class="subtitle">根据项目需求选择最适合的后端语言</p>
<div class="demo-header">
<span class="icon">🎯</span>
<span class="title">语言选择器</span>
<span class="subtitle">根据需求选择最合适的后端语言</span>
</div>
<div class="selection-flow">
<!-- Step 1: Project Type -->
<div class="step-card" :class="{ active: currentStep === 1 }">
<div class="step-number">1</div>
<h5>项目类型</h5>
<div class="options-grid">
<button
v-for="option in projectTypes"
:key="option.id"
class="option-btn"
:class="{ selected: answers.projectType === option.id }"
@click="selectProjectType(option.id)"
>
<span class="option-icon">{{ option.icon }}</span>
<span class="option-label">{{ option.label }}</span>
</button>
</div>
</div>
<div class="intro-text">
想象你在<span class="highlight">点餐</span>想吃快餐选 Python快速想吃大餐选 Java正式想吃健康餐选 Go平衡没有"最好的"选择只有"最合适"的选择
</div>
<!-- Step 2: Performance Requirement -->
<div class="questions-container">
<div
class="step-card"
:class="{ active: currentStep === 2, disabled: !answers.projectType }"
v-for="(question, index) in questions"
:key="question.id"
class="question-card"
:class="{ active: currentQuestion === index }"
>
<div class="step-number">2</div>
<h5>性能要求</h5>
<div class="options-grid">
<button
v-for="option in performanceLevels"
:key="option.id"
class="option-btn"
:class="{ selected: answers.performance === option.id }"
@click="selectPerformance(option.id)"
>
<span class="option-icon">{{ option.icon }}</span>
<span class="option-label">{{ option.label }}</span>
<span class="option-desc">{{ option.desc }}</span>
</button>
</div>
</div>
<!-- Step 3: Team Background -->
<div
class="step-card"
:class="{
active: currentStep === 3,
disabled: !answers.performance
}"
>
<div class="step-number">3</div>
<h5>团队背景</h5>
<div class="options-grid">
<button
v-for="option in teamBackgrounds"
:key="option.id"
class="option-btn"
:class="{ selected: answers.team === option.id }"
@click="selectTeam(option.id)"
>
<span class="option-icon">{{ option.icon }}</span>
<span class="option-label">{{ option.label }}</span>
</button>
</div>
</div>
<!-- Step 4: Time to Market -->
<div
class="step-card"
:class="{ active: currentStep === 4, disabled: !answers.team }"
>
<div class="step-number">4</div>
<h5>上市时间</h5>
<div class="options-grid">
<button
v-for="option in timeConstraints"
:key="option.id"
class="option-btn"
:class="{ selected: answers.time === option.id }"
@click="selectTime(option.id)"
>
<span class="option-icon">{{ option.icon }}</span>
<span class="option-label">{{ option.label }}</span>
<span class="option-desc">{{ option.desc }}</span>
</button>
<div class="question-number">{{ index + 1 }}</div>
<div class="question-content">
<h6>{{ question.text }}</h6>
<div class="options">
<button
v-for="option in question.options"
:key="option.value"
class="option-btn"
:class="{ selected: answers[index] === option.value }"
@click="selectAnswer(index, option.value)"
>
{{ option.label }}
</button>
</div>
</div>
</div>
</div>
<!-- Recommendation -->
<transition name="result">
<Transition name="fade">
<div v-if="recommendation" class="recommendation-panel">
<h5>🎉 推荐语言</h5>
<div class="recommendation-card">
<div class="rec-language">
<span class="rec-icon">{{ recommendation.icon }}</span>
<span class="rec-name">{{ recommendation.language }}</span>
</div>
<div class="rec-reason">
<h6>选择理由</h6>
<p>{{ recommendation.reason }}</p>
</div>
<div class="rec-alternatives">
<h6>备选方案</h6>
<div class="alt-list">
<span
v-for="alt in recommendation.alternatives"
:key="alt"
class="alt-tag"
>
{{ alt }}
</span>
</div>
<div class="rec-header">
<span class="rec-icon">{{ recommendation.icon }}</span>
<div class="rec-title">
<h6>推荐语言</h6>
<div class="rec-name">{{ recommendation.language }}</div>
</div>
</div>
<div class="rec-reason">
<strong>选择理由</strong>
<p>{{ recommendation.reason }}</p>
</div>
<button class="reset-btn" @click="reset">🔄 重新选择</button>
</div>
</transition>
</Transition>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>不要问"哪个语言最火"而要问"我的项目需要什么"初创公司优先开发速度Python/Node.js大厂优先稳定性和性能Java/Go系统编程优先安全Rust
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const currentStep = ref(1)
const answers = ref({
projectType: null,
performance: null,
team: null,
time: null
})
const currentQuestion = ref(0)
const answers = ref({})
const projectTypes = [
{ id: 'web', icon: '🌐', label: 'Web 应用' },
{ id: 'api', icon: '🔌', label: 'API 服务' },
{ id: 'microservice', icon: '⚙️', label: '微服务' },
{ id: 'ai', icon: '🤖', label: 'AI/ML' },
{ id: 'game', icon: '🎮', label: '游戏' },
{ id: 'system', icon: '💻', label: '系统编程' }
]
const performanceLevels = [
{ id: 'extreme', icon: '⚡', label: '极致性能', desc: '每秒百万级请求' },
{ id: 'high', icon: '🚀', label: '高性能', desc: '每秒十万级请求' },
{ id: 'medium', icon: '📊', label: '中等性能', desc: '每秒万级请求' },
{ id: 'low', icon: '🐌', label: '性能不敏感', desc: '快速开发优先' }
]
const teamBackgrounds = [
{ id: 'frontend', icon: '💚', label: '前端团队' },
{ id: 'python', icon: '🐍', label: 'Python 背景' },
{ id: 'java', icon: '☕', label: 'Java 背景' },
{ id: 'mixed', icon: '👥', label: '混合团队' },
{ id: 'new', icon: '🆕', label: '新团队' }
]
const timeConstraints = [
{ id: 'urgent', icon: '🔥', label: '紧急', desc: '1-2 周上线' },
{ id: 'normal', icon: '📅', label: '正常', desc: '1-2 个月' },
{ id: 'flexible', icon: '🎯', label: '灵活', desc: '3 个月以上' }
const questions = [
{
id: 'project_type',
text: '项目类型是什么?',
options: [
{ value: 'web', label: 'Web 应用' },
{ value: 'api', label: 'API 服务' },
{ value: 'ai', label: 'AI/ML' },
{ value: 'system', label: '系统编程' }
]
},
{
id: 'performance',
text: '性能要求如何?',
options: [
{ value: 'high', label: '高性能' },
{ value: 'medium', label: '中等' },
{ value: 'low', label: '不敏感' }
]
},
{
id: 'team',
text: '团队背景?',
options: [
{ value: 'frontend', label: '前端团队' },
{ value: 'python', label: 'Python 背景' },
{ value: 'java', label: 'Java 背景' },
{ value: 'new', label: '新团队' }
]
}
]
const recommendation = computed(() => {
if (
!answers.value.projectType ||
!answers.value.performance ||
!answers.value.team ||
!answers.value.time
) {
return null
}
if (Object.keys(answers.value).length < 3) return null
const { projectType, performance, team, time } = answers.value
const { project_type, performance, team } = answers.value
// 决策逻辑
if (projectType === 'ai') {
if (project_type === 'ai') {
return {
language: 'Python',
icon: '🐍',
reason:
'AI/ML 领域的绝对统治地位,生态无与伦比NumPy、PyTorch、TensorFlow。虽然性能不如 C++/Rust,但 95% 的 AI 项目都在用 Python。',
alternatives: ['C++ (模型部署)', 'Julia (科学计算)']
language: 'Python',
reason: 'AI/ML 的绝对统治地位,生态无与伦比。虽然性能不如 C++/Rust,但 95% 的 AI 项目都在用 Python。'
}
}
if (projectType === 'game') {
if (project_type === 'system' || performance === 'high') {
return {
language: 'C++',
icon: '⚡',
reason:
'游戏开发的行业标准(Unreal Engine)。极致性能,底层控制力强。如果使用 Unity 引擎,则 C# 是首选。',
alternatives: ['C# (Unity)', 'Rust (独立游戏)']
}
}
if (projectType === 'system') {
if (performance === 'extreme') {
return {
language: 'Rust',
icon: '🦀',
reason:
'内存安全 + 极致性能,现代化系统语言。虽然学习曲线陡峭,但编译时保证无内存泄漏,适合长期维护的基础设施。',
alternatives: ['C++ (传统选择)', 'Go (云原生)']
}
}
return {
language: 'Go',
icon: '🐹',
reason:
'云原生时代的宠儿Docker、K8s 都是 Go 写的)。简洁语法 + 原生并发 + 快速编译,非常适合系统编程和 DevOps 工具。',
alternatives: ['Rust (更安全)', 'C++ (更成熟)']
}
}
if (projectType === 'microservice') {
if (performance === 'extreme' || performance === 'high') {
return {
language: 'Go',
icon: '🐹',
reason:
'云原生的首选语言。Goroutine 轻量级并发可轻松处理百万级请求,编译后的单一可执行文件部署极其简单。',
alternatives: ['Java (Spring Cloud)', 'Rust (极致性能)']
}
}
return {
language: 'Node.js',
icon: '💚',
reason:
'前后端统一,减少语言切换成本。NPM 生态丰富,适合 I/O 密集型的微服务。',
alternatives: ['Go (更高性能)', 'Python (快速开发)']
language: 'Go',
reason: '云原生时代的宠儿,简洁语法 + 原生并发 + 快速编译。单一可执行文件部署极其简单。'
}
}
if (team === 'frontend') {
return {
language: 'Node.js',
icon: '💚',
reason:
'前端团队零学习成本,TypeScript 提供类型安全。全栈开发减少沟通成本,适合快速迭代和 MVP 开发。',
alternatives: ['Go (后端性能优化)', 'TypeScript (类型安全)']
language: 'Node.js',
reason: '前后端统一,减少语言切换成本。NPM 生态庞大,适合快速迭代和 MVP 开发。'
}
}
if (team === 'python') {
return {
language: 'Python',
icon: '🐍',
reason:
'利用团队现有技能,快速开发。Django/FastAPI 生态成熟,适合数据驱动的 Web 应用。',
alternatives: ['Go (性能提升)', 'Node.js (全栈)']
language: 'Python',
reason: '利用团队现有技能,快速开发。Django/FastAPI 生态成熟,适合数据驱动的应用。'
}
}
if (team === 'java') {
return {
language: 'Java',
icon: '☕',
reason:
'企业级开发的最佳选择。Spring Boot 生态极其成熟,团队熟悉度高,维护成本低。',
alternatives: ['Go (云原生)', 'Kotlin (更现代)']
language: 'Java',
reason: '企业级开发的最佳选择。Spring Boot 生态极其成熟,团队熟悉度高,维护成本低。'
}
}
if (time === 'urgent') {
if (projectType === 'web' || projectType === 'api') {
return {
language: 'Python',
icon: '🐍',
reason:
'开发速度最快的语言。FastAPI/Django 让你在几天内就能搭建起完整的 Web 应用,适合快速验证想法和 MVP。',
alternatives: ['Ruby (Rails)', 'Node.js (全栈)']
}
}
}
// 默认推荐
if (performance === 'extreme') {
return {
language: 'Go',
icon: '🐹',
reason:
'高性能 + 简洁语法 + 快速开发的最佳平衡点。Goroutine 并发模型让处理高并发变得简单,而不会像 Java 那么复杂。',
alternatives: ['Rust (更安全)', 'C++ (更极致)']
}
}
if (performance === 'high') {
return {
language: 'Go',
icon: '🐹',
reason:
'云原生时代的高性能语言。相比 Java 更简洁,相比 Node.js 性能更好,相比 C++ 更容易维护。',
alternatives: ['Java (更成熟)', 'Node.js (更灵活)']
}
}
// Default: Node.js or Python
return {
language: 'Node.js',
icon: '💚',
reason:
'前后端统一,生态庞大,适合大多数 Web 应用和 API 服务。NPM 拥有世界最大的包仓库,几乎任何功能都能找到现成的库。',
alternatives: ['Go (更高性能)', 'Python (更简单)']
icon: '🐹',
language: 'Go',
reason: '云原生时代的高性能语言。相比 Java 更简洁,相比 Node.js 性能更好,相比 Python 更稳定。'
}
})
const selectProjectType = (value) => {
answers.value.projectType = value
currentStep.value = 2
}
const selectPerformance = (value) => {
answers.value.performance = value
currentStep.value = 3
}
const selectTeam = (value) => {
answers.value.team = value
currentStep.value = 4
}
const selectTime = (value) => {
answers.value.time = value
currentStep.value = 5
const selectAnswer = (questionIndex, value) => {
answers.value[questionIndex] = value
if (currentQuestion.value < questions.length - 1) {
currentQuestion.value++
}
}
const reset = () => {
answers.value = {
projectType: null,
performance: null,
team: null,
time: null
}
currentStep.value = 1
answers.value = {}
currentQuestion.value = 0
}
</script>
<style scoped>
.language-selector-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
max-height: 600px;
overflow-y: auto;
}
.selector-header {
text-align: center;
margin-bottom: 3rem;
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.selector-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
.demo-header .icon {
font-size: 1.25rem;
}
.subtitle {
margin: 0;
.demo-header .title {
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
font-size: 0.95rem;
font-size: 0.85rem;
margin-left: 0.5rem;
}
.selection-flow {
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.questions-container {
display: flex;
flex-direction: column;
gap: 2rem;
}
.step-card {
background: var(--vp-c-bg-soft);
border: 2px solid var(--vp-c-divider);
border-radius: 12px;
padding: 2rem;
transition: all 0.3s ease;
}
.step-card.active {
border-color: var(--vp-c-brand);
box-shadow: 0 8px 30px rgba(59, 130, 246, 0.1);
}
.step-card.disabled {
opacity: 0.5;
pointer-events: none;
}
.step-number {
display: inline-block;
width: 32px;
height: 32px;
background: var(--vp-c-brand);
color: white;
border-radius: 50%;
text-align: center;
line-height: 32px;
font-weight: bold;
gap: 0.75rem;
margin-bottom: 1rem;
}
.step-card h5 {
margin: 0 0 1.5rem 0;
color: var(--vp-c-text-1);
font-size: 1.2rem;
}
.options-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 1rem;
}
.option-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
padding: 1.5rem 1rem;
.question-card {
background: var(--vp-c-bg);
border: 2px solid var(--vp-c-divider);
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
padding: 0.75rem;
border-radius: 6px;
border: 2px solid transparent;
display: flex;
gap: 0.75rem;
}
.option-btn:hover:not(.selected) {
.question-card.active {
border-color: var(--vp-c-brand);
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);
}
.option-btn.selected {
border-color: var(--vp-c-brand);
.question-number {
width: 28px;
height: 28px;
background: var(--vp-c-brand);
color: white;
}
.option-icon {
font-size: 2rem;
line-height: 1;
}
.option-label {
font-weight: 600;
font-size: 0.95rem;
}
.option-desc {
font-size: 0.75rem;
opacity: 0.8;
text-align: center;
}
.recommendation-panel {
margin-top: 3rem;
animation: slide-up 0.5s ease;
}
.recommendation-panel h5 {
text-align: center;
margin: 0 0 2rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.recommendation-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16px;
padding: 2.5rem;
color: white;
box-shadow: 0 10px 40px rgba(102, 126, 234, 0.4);
}
.rec-language {
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin-bottom: 2rem;
font-weight: bold;
font-size: 0.85rem;
flex-shrink: 0;
}
.question-content {
flex: 1;
}
.question-content h6 {
margin: 0 0 0.5rem 0;
font-size: 0.9rem;
color: var(--vp-c-text-1);
}
.options {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.option-btn {
padding: 0.35rem 0.75rem;
background: var(--vp-c-bg-soft);
border: 2px solid transparent;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
font-size: 0.8rem;
}
.option-btn:hover {
border-color: var(--vp-c-brand);
}
.option-btn.selected {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.recommendation-panel {
background: var(--vp-c-bg);
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
border: 2px solid var(--vp-c-brand);
}
.rec-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
}
.rec-icon {
font-size: 4rem;
line-height: 1;
font-size: 2.5rem;
}
.rec-title h6 {
margin: 0 0 0.25rem 0;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.rec-name {
font-size: 2.5rem;
font-size: 1.5rem;
font-weight: bold;
color: var(--vp-c-brand-1);
}
.rec-reason,
.rec-alternatives {
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
backdrop-filter: blur(10px);
.rec-reason {
margin-bottom: 0.75rem;
}
.rec-reason h6,
.rec-alternatives h6 {
margin: 0 0 1rem 0;
font-size: 1.1rem;
opacity: 0.9;
.rec-reason strong {
display: block;
margin-bottom: 0.25rem;
font-size: 0.85rem;
color: var(--vp-c-text-1);
}
.rec-reason p {
margin: 0;
line-height: 1.7;
font-size: 0.95rem;
}
.alt-list {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
}
.alt-tag {
background: rgba(255, 255, 255, 0.2);
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.9rem;
font-weight: 600;
font-size: 0.85rem;
color: var(--vp-c-text-2);
line-height: 1.5;
}
.reset-btn {
display: block;
width: 100%;
padding: 1rem;
background: white;
color: #667eea;
padding: 0.5rem;
background: var(--vp-c-brand);
color: white;
border: none;
border-radius: 8px;
font-size: 1rem;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
transition: all 0.2s ease;
font-size: 0.85rem;
}
.reset-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
background: var(--vp-c-brand-dark);
}
.result-enter-active,
.result-leave-active {
transition: all 0.5s ease;
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.result-enter-from {
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(30px);
}
.result-leave-to {
opacity: 0;
transform: translateY(-30px);
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 768px) {
.options-grid {
grid-template-columns: repeat(2, 1fr);
}
.rec-name {
font-size: 2rem;
}
.rec-icon {
font-size: 3rem;
}
.info-box .icon {
margin-right: 0.25rem;
}
</style>
@@ -1,18 +1,40 @@
<template>
<div class="memory-management-demo">
<div class="demo-header">
<h4>内存管理机制可视化</h4>
<span class="icon">🧠</span>
<span class="title">内存管理</span>
<span class="subtitle">不同语言的内存处理方式</span>
</div>
<div class="memory-models">
<div class="model-card" v-for="model in models" :key="model.name">
<div class="intro-text">
想象你在<span class="highlight">收拾房间</span>有的房间有自动扫地机器人定期清理GC有的需要自己动手整理手动管理有的房间设计得不会变乱所有权系统
</div>
<div class="models-container">
<div
v-for="model in models"
:key="model.name"
class="model-card"
>
<div class="model-icon">{{ model.icon }}</div>
<div class="model-name">{{ model.name }}</div>
<div class="model-desc">{{ model.desc }}</div>
<div class="model-desc">{{ model.description }}</div>
<div class="model-languages">
<span v-for="lang in model.languages" :key="lang" class="lang-tag">{{ lang }}</span>
<span
v-for="lang in model.languages"
:key="lang"
class="lang-tag"
>
{{ lang }}
</span>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>GC 语言JavaGoPython让开发者省心但有性能开销手动管理CC++性能最好但容易内存泄漏Rust 的所有权系统编译时保证安全无运行时开销
</div>
</div>
</template>
@@ -21,19 +43,19 @@ const models = [
{
name: '垃圾回收 (GC)',
icon: '♻️',
desc: '运行时自动回收不再使用的内存',
description: '运行时自动回收不再使用的内存',
languages: ['Java', 'Go', 'Python', 'Node.js']
},
{
name: '手动管理',
icon: '🔧',
desc: '开发者显式申请和释放内存',
description: '开发者显式申请和释放内存',
languages: ['C', 'C++']
},
{
name: '所有权系统',
icon: '🔒',
desc: '编译时通过规则保证内存安全',
description: '编译时通过规则保证内存安全',
languages: ['Rust']
}
]
@@ -43,41 +65,109 @@ const models = [
.memory-management-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
padding: 20px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
max-height: 600px;
overflow-y: auto;
}
.memory-models {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-top: 20px;
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.model-card {
padding: 16px;
.demo-header .icon {
font-size: 1.25rem;
}
.demo-header .title {
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
font-size: 0.85rem;
margin-left: 0.5rem;
}
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.models-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 0.75rem;
margin-bottom: 1rem;
}
.model-card {
background: var(--vp-c-bg);
padding: 1rem;
border-radius: 6px;
text-align: center;
border: 1px solid var(--vp-c-divider);
}
.model-icon {
font-size: 2em;
margin-bottom: 8px;
font-size: 2rem;
margin-bottom: 0.5rem;
}
.model-name {
font-weight: bold;
margin-bottom: 4px;
font-weight: 600;
font-size: 0.9rem;
color: var(--vp-c-text-1);
margin-bottom: 0.25rem;
}
.model-desc {
font-size: 0.9em;
font-size: 0.8rem;
color: var(--vp-c-text-2);
margin-bottom: 12px;
margin-bottom: 0.75rem;
line-height: 1.4;
}
.model-languages {
display: flex;
flex-wrap: wrap;
gap: 0.35rem;
justify-content: center;
}
.lang-tag {
display: inline-block;
padding: 2px 6px;
margin: 2px;
background: var(--vp-c-bg-mute);
padding: 0.2rem 0.5rem;
background: var(--vp-c-bg-soft);
border-radius: 4px;
font-size: 0.8em;
font-size: 0.7rem;
color: var(--vp-c-brand-1);
font-weight: 600;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.info-box .icon {
margin-right: 0.25rem;
}
</style>
@@ -1,45 +1,41 @@
<template>
<div class="performance-benchmark-demo">
<div class="benchmark-controls">
<h4>性能基准测试</h4>
<div class="control-group">
<label>测试场景</label>
<div class="demo-header">
<span class="icon">🏁</span>
<span class="title">性能赛道</span>
<span class="subtitle">不同语言的竞速测试</span>
</div>
<div class="intro-text">
想象你在<span class="highlight">赛车场</span>F1 赛车C++Rust速度极快但难以驾驭家用轿车PythonRuby舒适但速度慢跑车GoJava在速度和操控之间取得平衡
</div>
<div class="control-panel">
<div class="scenario-selector">
<label>选择赛道</label>
<select v-model="selectedScenario" @change="runBenchmark">
<option value="hello">Hello World (简单 HTTP)</option>
<option value="json">JSON 序列化</option>
<option value="db">数据库查询</option>
<option value="compute">CPU 密集计算</option>
<option v-for="scenario in scenarios" :key="scenario.id" :value="scenario.id">
{{ scenario.label }}
</option>
</select>
</div>
<button class="run-btn" @click="runBenchmark" :disabled="isRunning">
{{ isRunning ? '测试中...' : '▶ 运行测试' }}
{{ isRunning ? '测试中...' : '▶ 开始测试' }}
</button>
</div>
<div class="results-panel">
<div class="results-header">
<h5>测试结果Requests/Second</h5>
<div class="legend">
<span class="legend-item"
><span class="dot" style="background: #f59e0b"></span> 高性能</span
>
<span class="legend-item"
><span class="dot" style="background: #10b981"></span> 中等</span
>
<span class="legend-item"
><span class="dot" style="background: #6366f1"></span> 较低</span
>
</div>
<div class="panel-header">
<span class="panel-title">测试结果Requests/Second</span>
</div>
<transition-group name="bar" tag="div" class="chart-container">
<div class="bars-container">
<div
v-for="result in sortedResults"
:key="result.language"
class="chart-bar-wrapper"
class="bar-wrapper"
>
<div class="bar-label">{{ result.language }}</div>
<div class="bar-container">
<div class="bar-track">
<div
class="bar-fill"
:class="getBarClass(result.rps)"
@@ -49,14 +45,12 @@
</div>
</div>
</div>
</transition-group>
</div>
</div>
<div class="explanation-panel">
<h5>💡 性能解释</h5>
<div class="explanation-content">
<p>{{ getCurrentExplanation() }}</p>
</div>
<div class="info-box">
<span class="icon">💡</span>
<span>{{ getCurrentExplanation() }}</span>
</div>
</div>
</template>
@@ -67,56 +61,57 @@ import { ref, computed } from 'vue'
const selectedScenario = ref('hello')
const isRunning = ref(false)
const scenarios = [
{ id: 'hello', label: '🏁 简单 HTTP (Hello World)' },
{ id: 'json', label: '📦 JSON 序列化' },
{ id: 'db', label: '🗄️ 数据库查询' },
{ id: 'compute', label: '⚙️ CPU 密集计算' }
]
const benchmarkData = {
hello: {
'C++': { rps: 1500000, time: 0.5 },
Rust: { rps: 1200000, time: 0.6 },
Go: { rps: 1000000, time: 0.7 },
Java: { rps: 700000, time: 1.0 },
'Node.js': { rps: 800000, time: 0.9 },
Python: { rps: 200000, time: 2.5 },
Ruby: { rps: 150000, time: 3.0 },
PHP: { rps: 250000, time: 2.0 }
},
json: {
'C++': { rps: 800000, time: 1.0 },
Rust: { rps: 700000, time: 1.1 },
Go: { rps: 600000, time: 1.2 },
Java: { rps: 500000, time: 1.5 },
'Node.js': { rps: 450000, time: 1.6 },
Python: { rps: 150000, time: 4.0 },
Ruby: { rps: 120000, time: 5.0 },
PHP: { rps: 180000, time: 3.5 }
},
db: {
'C++': { rps: 300000, time: 2.5 },
Rust: { rps: 280000, time: 2.6 },
Go: { rps: 250000, time: 3.0 },
Java: { rps: 200000, time: 3.5 },
'Node.js': { rps: 220000, time: 3.2 },
Python: { rps: 80000, time: 8.0 },
Ruby: { rps: 70000, time: 9.0 },
PHP: { rps: 90000, time: 7.5 }
},
compute: {
'C++': { rps: 500000, time: 1.5 },
Rust: { rps: 480000, time: 1.6 },
Go: { rps: 400000, time: 2.0 },
Java: { rps: 350000, time: 2.3 },
'Node.js': { rps: 50000, time: 15.0 },
Python: { rps: 30000, time: 25.0 },
Ruby: { rps: 25000, time: 30.0 },
PHP: { rps: 35000, time: 20.0 }
}
hello: [
{ language: 'C++', rps: 1500000 },
{ language: 'Rust', rps: 1200000 },
{ language: 'Go', rps: 1000000 },
{ language: 'Node.js', rps: 800000 },
{ language: 'Java', rps: 700000 },
{ language: 'Python', rps: 200000 },
{ language: 'Ruby', rps: 150000 }
],
json: [
{ language: 'C++', rps: 800000 },
{ language: 'Rust', rps: 700000 },
{ language: 'Go', rps: 600000 },
{ language: 'Node.js', rps: 450000 },
{ language: 'Java', rps: 500000 },
{ language: 'Python', rps: 150000 },
{ language: 'Ruby', rps: 120000 }
],
db: [
{ language: 'C++', rps: 300000 },
{ language: 'Rust', rps: 280000 },
{ language: 'Go', rps: 250000 },
{ language: 'Node.js', rps: 220000 },
{ language: 'Java', rps: 200000 },
{ language: 'Python', rps: 80000 },
{ language: 'Ruby', rps: 70000 }
],
compute: [
{ language: 'C++', rps: 500000 },
{ language: 'Rust', rps: 480000 },
{ language: 'Go', rps: 400000 },
{ language: 'Java', rps: 350000 },
{ language: 'Node.js', rps: 50000 },
{ language: 'Python', rps: 30000 },
{ language: 'Ruby', rps: 25000 }
]
}
const explanations = {
hello:
'简单的 Hello World HTTP 响应测试。C++ 和 Rust 在这个测试中展现出接近硬件的性能优势。Go 和 Node.js 表现也很优秀,因为它们的 HTTP 栈经过高度优化。Python 和 Ruby 由于解释器开销,性能相对较低。',
json: 'JSON 序列化/反序列化测试。这个测试考验语言的 JSON 处理能力。C++ 和 Rust 依然领先,但 Node.js 的表现也不错(V8 引擎优化)。Python 的标准库 json 模块性能尚可,但比编译型语言慢很多。',
db: '模拟数据库查询(连接池 + 查询)。这个测试更接近真实应用。性能差距缩小了,因为瓶颈主要在数据库 I/O 而非语言本身。但依然能看到编译型语言(C++、Rust、Go)的优势。',
compute:
'CPU 密集型计算(斐波那契数列)。这个测试充分暴露了 Node.js 的短板:单线程 + V8 编译优化不如静态语言。Python 和 Ruby 表现最差,因为它们是解释型语言,且 GIL 限制了多线程性能。C++ 和 Rust 几乎是唯一选择。'
hello: '简单的 HTTP 响应测试。C++ 和 Rust 展现出接近硬件的性能优势。Go 和 Node.js 表现优秀(HTTP 栈经过高度优化)。Python 和 Ruby 由于解释器开销,性能相对较低。',
json: 'JSON 序列化测试。C++ 和 Rust 依然领先,Node.js 的 V8 引擎优化让它的表现也不错。Python 标准库 json 模块性能尚可,但比编译型语言慢很多。',
db: '模拟数据库查询。性能差距缩小,因为瓶颈主要在数据库 I/O。但编译型语言(C++、Rust、Go)的优势依然明显。',
compute: 'CPU 密集型计算(斐波那契)。Node.js 的短板暴露:单线程 + V8 优化不如静态语言。Python 和 Ruby 表现最差(解释型语言 + GIL 限制)。'
}
const currentResults = ref([])
@@ -129,16 +124,10 @@ const runBenchmark = () => {
isRunning.value = true
currentResults.value = []
// 模拟测试延迟
setTimeout(() => {
const data = benchmarkData[selectedScenario.value]
currentResults.value = Object.entries(data).map(([language, stats]) => ({
language,
rps: stats.rps,
time: stats.time
}))
currentResults.value = benchmarkData[selectedScenario.value]
isRunning.value = false
}, 1000)
}, 800)
}
const getBarWidth = (rps) => {
@@ -147,8 +136,8 @@ const getBarWidth = (rps) => {
}
const getBarClass = (rps) => {
if (rps >= 800000) return 'bar-high'
if (rps >= 300000) return 'bar-medium'
if (rps >= 500000) return 'bar-high'
if (rps >= 200000) return 'bar-medium'
return 'bar-low'
}
@@ -162,69 +151,106 @@ const getCurrentExplanation = () => {
return explanations[selectedScenario.value]
}
// 初始运行一次
runBenchmark()
</script>
<style scoped>
.performance-benchmark-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
max-height: 600px;
overflow-y: auto;
}
.benchmark-controls {
display: flex;
align-items: center;
gap: 1.5rem;
margin-bottom: 2rem;
flex-wrap: wrap;
}
.benchmark-controls h4 {
margin: 0;
color: var(--vp-c-brand);
font-size: 1.2rem;
}
.control-group {
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.control-group label {
.demo-header .icon {
font-size: 1.25rem;
}
.demo-header .title {
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
font-size: 0.85rem;
margin-left: 0.5rem;
}
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.control-panel {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
}
.scenario-selector {
display: flex;
align-items: center;
gap: 0.5rem;
flex: 1;
}
.scenario-selector label {
font-size: 0.85rem;
font-weight: 600;
color: var(--vp-c-text-1);
}
.control-group select {
padding: 0.5rem 1rem;
.scenario-selector select {
padding: 0.4rem 0.75rem;
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
background: var(--vp-c-bg);
background: var(--vp-c-bg-alt);
color: var(--vp-c-text-1);
font-size: 0.9rem;
font-size: 0.85rem;
cursor: pointer;
}
.run-btn {
padding: 0.5rem 1.5rem;
padding: 0.4rem 0.8rem;
background: var(--vp-c-brand);
color: white;
border: none;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
transition: all 0.2s;
font-size: 0.85rem;
}
.run-btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
background: var(--vp-c-brand-dark);
}
.run-btn:disabled {
@@ -233,68 +259,47 @@ runBenchmark()
}
.results-panel {
margin-bottom: 2rem;
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.results-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
flex-wrap: wrap;
gap: 1rem;
.panel-header {
margin-bottom: 0.75rem;
}
.results-header h5 {
margin: 0;
.panel-title {
font-weight: 600;
font-size: 0.9rem;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.legend {
display: flex;
gap: 1rem;
font-size: 0.85rem;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.3rem;
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.chart-container {
.bars-container {
display: flex;
flex-direction: column;
gap: 1rem;
gap: 0.5rem;
}
.chart-bar-wrapper {
.bar-wrapper {
display: flex;
align-items: center;
gap: 1rem;
gap: 0.5rem;
}
.bar-label {
min-width: 80px;
min-width: 70px;
font-size: 0.8rem;
font-weight: 600;
color: var(--vp-c-text-1);
font-size: 0.9rem;
}
.bar-container {
.bar-track {
flex: 1;
height: 40px;
height: 24px;
background: var(--vp-c-bg-soft);
border-radius: 8px;
border-radius: 4px;
overflow: hidden;
position: relative;
}
.bar-fill {
@@ -302,87 +307,35 @@ runBenchmark()
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 1rem;
transition: width 0.8s ease-out;
padding-right: 0.5rem;
transition: width 0.5s ease;
color: white;
font-weight: 700;
font-size: 0.9rem;
font-weight: 600;
font-size: 0.75rem;
}
.bar-high {
background: linear-gradient(90deg, #f59e0b, #d97706);
background: var(--vp-c-green-1);
}
.bar-medium {
background: linear-gradient(90deg, #10b981, #059669);
background: var(--vp-c-yellow-1);
}
.bar-low {
background: linear-gradient(90deg, #6366f1, #4f46e5);
background: var(--vp-c-brand-1);
}
.bar-enter-active,
.bar-leave-active {
transition: all 0.5s ease;
}
.bar-enter-from {
opacity: 0;
transform: translateX(-30px);
}
.bar-leave-to {
opacity: 0;
transform: translateX(30px);
}
.explanation-panel {
background: var(--vp-c-bg-soft);
border-radius: 8px;
padding: 1.5rem;
border-left: 4px solid var(--vp-c-brand);
}
.explanation-panel h5 {
margin-top: 0;
margin-bottom: 1rem;
color: var(--vp-c-brand);
font-size: 1.1rem;
}
.explanation-content p {
margin: 0;
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
line-height: 1.7;
font-size: 0.95rem;
line-height: 1.5;
}
@media (max-width: 768px) {
.benchmark-controls {
flex-direction: column;
align-items: stretch;
}
.control-group {
flex: 1;
}
.run-btn {
width: 100%;
}
.results-header {
flex-direction: column;
align-items: flex-start;
}
.bar-label {
min-width: 60px;
font-size: 0.8rem;
}
.bar-value {
font-size: 0.8rem;
}
.info-box .icon {
margin-right: 0.25rem;
}
</style>
@@ -1,80 +1,58 @@
<template>
<div class="syntax-comparison-demo">
<div class="demo-header">
<h4>Hello World 语法对比</h4>
<p class="subtitle">同样的功能不同的实现方式</p>
<span class="icon">📝</span>
<span class="title">语法对比镜</span>
<span class="subtitle">同样的功能不同的表达方式</span>
</div>
<div class="language-selector">
<div class="intro-text">
想象你在<span class="highlight">写信</span>有人喜欢简洁明了PythonRuby有人喜欢正式严谨JavaC#有人喜欢直接高效Go不同语言的语法反映了不同的设计哲学
</div>
<div class="language-tabs">
<button
v-for="lang in languages"
:key="lang.name"
class="lang-btn"
class="lang-tab"
:class="{ active: selectedLang === lang.name }"
@click="selectedLang = lang.name"
>
<span class="lang-icon">{{ lang.icon }}</span>
<span class="lang-name">{{ lang.name }}</span>
<span class="tab-icon">{{ lang.icon }}</span>
<span class="tab-name">{{ lang.name }}</span>
</button>
</div>
<transition name="fade" mode="out-in">
<Transition name="fade" mode="out-in">
<div :key="selectedLang" class="code-display">
<div class="code-header">
<div class="window-controls">
<span class="control red"></span>
<span class="control yellow"></span>
<span class="control green"></span>
<div class="code-window">
<div class="window-header">
<div class="window-controls">
<span class="control red"></span>
<span class="control yellow"></span>
<span class="control green"></span>
</div>
<div class="file-name">{{ getCode(selectedLang).filename }}</div>
</div>
<div class="filename">{{ getFileName(selectedLang) }}</div>
<pre class="code-content">{{ getCode(selectedLang).code }}</pre>
</div>
<pre class="code-content"><code>{{ getCode(selectedLang) }}</code></pre>
<div class="code-stats">
<div class="stat-item">
<span class="stat-label">代码行数</span>
<span class="stat-value">{{ getLineCount(selectedLang) }} </span>
</div>
<div class="stat-item">
<span class="stat-label">字符数</span>
<span class="stat-value"
>{{ getCharCount(selectedLang) }} 字符</span
>
</div>
<div class="stat-item">
<span class="stat-label">复杂度</span>
<span class="stat-value">{{ getComplexity(selectedLang) }}</span>
<span class="stat-value">{{ getCode(selectedLang).complexity }}</span>
</div>
</div>
</div>
</transition>
</Transition>
<div class="analysis-panel">
<h5>💡 语法分析</h5>
<div class="analysis-content">
<p>{{ getAnalysis(selectedLang) }}</p>
</div>
</div>
<div class="complexity-chart">
<h5>代码复杂度对比</h5>
<div class="chart-bars">
<div
v-for="lang in languages"
:key="lang.name"
class="chart-bar-wrapper"
>
<div class="chart-label">{{ lang.name }}</div>
<div class="chart-bar">
<div
class="chart-fill"
:style="{ width: getComplexityWidth(lang.name) + '%' }"
></div>
</div>
<div class="chart-value">{{ getLineCount(lang.name) }} </div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>简洁的语法PythonRuby让开发更快但冗长的语法JavaC#提供了更强的类型安全性和可维护性没有"最好"的语法只有最适合团队的语法
</div>
</div>
</template>
@@ -86,13 +64,10 @@ const selectedLang = ref('Python')
const languages = [
{ name: 'Python', icon: '🐍' },
{ name: 'Ruby', icon: '💎' },
{ name: 'Go', icon: '🐹' },
{ name: 'Node.js', icon: '💚' },
{ name: 'Java', icon: '☕' },
{ name: 'C#', icon: '💜' },
{ name: 'Rust', icon: '🦀' },
{ name: 'C++', icon: '⚡' }
{ name: 'Rust', icon: '🦀' }
]
const codes = {
@@ -101,11 +76,6 @@ const codes = {
filename: 'hello.py',
complexity: '极简'
},
Ruby: {
code: `puts "Hello, World!"`,
filename: 'hello.rb',
complexity: '极简'
},
Go: {
code: `package main
@@ -131,175 +101,136 @@ func main() {
filename: 'HelloWorld.java',
complexity: '冗长'
},
'C#': {
code: `using System;
class Program {
static void Main() {
Console.WriteLine("Hello, World!");
}
}`,
filename: 'Program.cs',
complexity: '冗长'
},
Rust: {
code: `fn main() {
println!("Hello, World!");
}`,
filename: 'main.rs',
complexity: '简洁'
},
'C++': {
code: `#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}`,
filename: 'hello.cpp',
complexity: '中等'
}
}
const analyses = {
Python:
'Python 的语法极其简洁,只有一行代码。这也是为什么它被称为"伪代码语言"——读起来就像英语一样自然。没有任何样板代码,直接表达意图。',
Ruby: 'Ruby 受 Perl 影响,语法非常优雅。puts 是 "put string" 的缩写,字符串不需要括号(虽然可以加)。Ruby 哲学是"程序员快乐至上"。',
Go: 'Go 的语法虽然比 Python 冗长,但非常清晰。package main、import、func main() 都是必要的显式声明,这让代码更容易理解和维护。',
'Node.js':
'Node.js 使用 JavaScript,语法简单直接。console.log() 是浏览器和 Node.js 通用的输出方式。前端开发者零学习成本。',
Java: 'Java 是典型的"仪式感"语言。class、public static void main、String[] args 都是必须的样板代码。虽然冗长,但结构清晰,适合大型项目。',
'C#': 'C# 和 Java 非常相似,同样需要 class 和 Main 方法。using System 类似 Java 的 import,但更现代一些。.NET Core 后跨平台能力大幅提升。',
Rust: 'Rust 的 fn main() 和 println! 宏看起来简洁,但 println! 后面的 ! 表示这是一个宏(不是函数)。Rust 的简洁来自于零成本抽象的设计哲学。',
'C++':
'C++ 需要 #include 头文件,std::cout 使用流操作符 <<return 0 表示程序成功退出。虽然比 C 语言简洁(printf),但依然保留了很多底层细节。'
}
const getCode = (lang) => {
return codes[lang].code
}
const getFileName = (lang) => {
return codes[lang].filename
return codes[lang]
}
const getLineCount = (lang) => {
return codes[lang].code.split('\n').length
}
const getCharCount = (lang) => {
return codes[lang].code.replace(/\s/g, '').length
}
const getComplexity = (lang) => {
return codes[lang].complexity
}
const getAnalysis = (lang) => {
return analyses[lang]
}
const getComplexityWidth = (lang) => {
const max = 10 // Java is the longest
const lines = getLineCount(lang)
return (lines / max) * 100
}
</script>
<style scoped>
.syntax-comparison-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
max-height: 600px;
overflow-y: auto;
}
.demo-header {
text-align: center;
margin-bottom: 2rem;
}
.demo-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.subtitle {
margin: 0;
color: var(--vp-c-text-2);
font-size: 0.95rem;
}
.language-selector {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-bottom: 2rem;
justify-content: center;
}
.lang-btn {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.25rem;
border: 2px solid var(--vp-c-divider);
border-radius: 8px;
margin-bottom: 0.75rem;
}
.demo-header .icon {
font-size: 1.25rem;
}
.demo-header .title {
font-weight: bold;
font-size: 1rem;
}
.demo-header .subtitle {
color: var(--vp-c-text-2);
font-size: 0.85rem;
margin-left: 0.5rem;
}
.intro-text {
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.6;
margin-bottom: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.intro-text .highlight {
color: var(--vp-c-brand-1);
font-weight: 500;
}
.language-tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
overflow-x: auto;
padding-bottom: 0.25rem;
}
.lang-tab {
display: flex;
align-items: center;
gap: 0.25rem;
padding: 0.5rem 0.75rem;
background: var(--vp-c-bg);
border: 2px solid transparent;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 600;
color: var(--vp-c-text-1);
transition: all 0.2s ease;
font-size: 0.85rem;
}
.lang-btn:hover {
.lang-tab:hover {
border-color: var(--vp-c-brand);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.lang-btn.active {
border-color: var(--vp-c-brand);
.lang-tab.active {
background: var(--vp-c-brand);
color: white;
}
.lang-icon {
font-size: 1.5rem;
line-height: 1;
}
.lang-name {
font-size: 0.95rem;
.tab-icon {
font-size: 1rem;
}
.code-display {
background: #1e1e1e;
border-radius: 12px;
overflow: hidden;
margin-bottom: 2rem;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
background: var(--vp-c-bg);
border-radius: 6px;
padding: 0.75rem;
margin-bottom: 1rem;
}
.code-header {
.code-window {
background: #1e1e1e;
border-radius: 6px;
overflow: hidden;
margin-bottom: 0.75rem;
}
.window-header {
display: flex;
align-items: center;
padding: 0.8rem 1rem;
padding: 0.5rem 0.75rem;
background: #2d2d2d;
border-bottom: 1px solid #3e3e3e;
gap: 0.5rem;
}
.window-controls {
display: flex;
gap: 6px;
gap: 4px;
}
.control {
width: 12px;
height: 12px;
width: 10px;
height: 10px;
border-radius: 50%;
}
@@ -315,131 +246,47 @@ const getComplexityWidth = (lang) => {
background: #27c93f;
}
.filename {
.file-name {
flex: 1;
text-align: center;
color: #858585;
font-size: 0.85rem;
font-size: 0.75rem;
font-family: var(--vp-font-family-mono);
}
.code-content {
margin: 0;
padding: 1.5rem;
padding: 1rem;
background: #1e1e1e;
color: #d4d4d4;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 0.9rem;
line-height: 1.6;
font-family: 'Monaco', 'Menlo', monospace;
font-size: 0.85rem;
line-height: 1.5;
overflow-x: auto;
}
.code-content code {
color: #d4d4d4;
}
.code-stats {
display: flex;
gap: 2rem;
padding: 1rem 1.5rem;
background: #2d2d2d;
border-top: 1px solid #3e3e3e;
flex-wrap: wrap;
gap: 1rem;
}
.stat-item {
display: flex;
gap: 0.5rem;
font-size: 0.85rem;
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.stat-label {
color: #858585;
margin-right: 0.25rem;
}
.stat-value {
color: #4ec9b0;
color: var(--vp-c-brand-1);
font-weight: 600;
font-family: var(--vp-font-family-mono);
}
.analysis-panel {
background: var(--vp-c-bg-soft);
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 2rem;
border-left: 4px solid var(--vp-c-brand);
}
.analysis-panel h5 {
margin-top: 0;
margin-bottom: 1rem;
color: var(--vp-c-brand);
font-size: 1.1rem;
}
.analysis-content p {
margin: 0;
color: var(--vp-c-text-2);
line-height: 1.7;
font-size: 0.95rem;
}
.complexity-chart {
margin-top: 2rem;
}
.complexity-chart h5 {
margin-bottom: 1.5rem;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.chart-bars {
display: flex;
flex-direction: column;
gap: 1rem;
}
.chart-bar-wrapper {
display: flex;
align-items: center;
gap: 1rem;
}
.chart-label {
min-width: 80px;
font-weight: 600;
color: var(--vp-c-text-1);
font-size: 0.9rem;
}
.chart-bar {
flex: 1;
height: 30px;
background: var(--vp-c-bg-soft);
border-radius: 6px;
overflow: hidden;
}
.chart-fill {
height: 100%;
background: linear-gradient(90deg, var(--vp-c-brand), #8b5cf6);
transition: width 0.5s ease;
}
.chart-value {
min-width: 60px;
text-align: right;
font-weight: 600;
color: var(--vp-c-text-2);
font-size: 0.85rem;
font-family: var(--vp-font-family-mono);
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
transition: opacity 0.2s ease;
}
.fade-enter-from,
@@ -447,30 +294,15 @@ const getComplexityWidth = (lang) => {
opacity: 0;
}
@media (max-width: 768px) {
.language-selector {
font-size: 0.85rem;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.lang-btn {
padding: 0.5rem 1rem;
}
.code-stats {
flex-direction: column;
gap: 0.75rem;
}
.chart-bar-wrapper {
flex-wrap: wrap;
}
.chart-label {
min-width: 60px;
}
.chart-value {
min-width: 50px;
}
.info-box .icon {
margin-right: 0.25rem;
}
</style>