Hello World - 标签页与模态框

知识库
知识库文档
/tech-stacks/alpinejs/examples/Hello World - 标签页与模态框.md

文档

Alpine.js 标签页与模态框

目标

用纯 HTML + Alpine.js 指令实现标签页切换和模态弹窗——无需写一行 JS。

完整代码

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>Alpine.js Demo</title>
  <style>
    body { font-family: system-ui; max-width: 600px; margin: 50px auto; background: #f8fafc; padding: 20px; }
    .tabs { display: flex; gap: 0; margin-bottom: 0; }
    .tab-btn { padding: 10px 20px; border: 1px solid #e2e8f0; background: #f1f5f9; cursor: pointer; border-bottom: none; border-radius: 8px 8px 0 0; }
    .tab-btn.active { background: white; color: #3b82f6; font-weight: bold; }
    .tab-panel { background: white; padding: 24px; border: 1px solid #e2e8f0; border-radius: 0 0 8px 8px; min-height: 150px; }
    .modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 100; }
    .modal-box { background: white; padding: 30px; border-radius: 12px; max-width: 400px; width: 90%; box-shadow: 0 20px 60px rgba(0,0,0,0.3); }
    .btn { padding: 10px 20px; background: #3b82f6; color: white; border: none; border-radius: 6px; cursor: pointer; }
    .btn-danger { background: #ef4444; }
    .toast { position: fixed; bottom: 20px; right: 20px; padding: 12px 24px; border-radius: 8px; color: white; animation: slideIn 0.3s ease; }
    @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
  </style>
  <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>

  <h1>🏗 Alpine.js Demo</h1>
  <p style="color: #666;">纯 HTML 属性驱动的交互 —— 零 JS 代码</p>

  <!-- 标签页组件 -->
  <div x-data="{ activeTab: 'vue' }">
    <div class="tabs">
      <button class="tab-btn" :class="{ active: activeTab === 'vue' }" @click="activeTab = 'vue'">Vue</button>
      <button class="tab-btn" :class="{ active: activeTab === 'react' }" @click="activeTab = 'react'">React</button>
      <button class="tab-btn" :class="{ active: activeTab === 'svelte' }" @click="activeTab = 'svelte'">Svelte</button>
    </div>
    <div class="tab-panel">
      <div x-show="activeTab === 'vue'">
        <h3>Vue 3</h3>
        <p>渐进式框架,尤雨溪创建。Composition API + 响应式系统。</p>
      </div>
      <div x-show="activeTab === 'react'">
        <h3>React 18</h3>
        <p>Facebook 出品,函数式组件 + Hooks 生态丰富。</p>
      </div>
      <div x-show="activeTab === 'svelte'">
        <h3>Svelte</h3>
        <p>编译时框架,无虚拟 DOM,极致轻量。</p>
      </div>
    </div>
  </div>

  <!-- 模态框 + Toast -->
  <div x-data="{ showModal: false, toast: '' }" style="margin-top: 30px; text-align: center;">
    <button class="btn" @click="showModal = true">打开详情</button>

    <!-- 模态框 -->
    <div x-show="showModal" class="modal-overlay" @click.self="showModal = false">
      <div class="modal-box" @click.stop>
        <h2>📄 项目详情</h2>
        <p><strong>项目名称:</strong>校园二手交易平台</p>
        <p><strong>技术栈:</strong>Vue3 + NestJS + MySQL</p>
        <p><strong>完成度:</strong>85%</p>
        <div style="display: flex; gap: 10px; margin-top: 20px;">
          <button class="btn" @click="showModal = false; toast = '已确认提交 ✅'">确认</button>
          <button class="btn btn-danger" @click="showModal = false">取消</button>
        </div>
      </div>
    </div>

    <!-- Toast 通知 -->
    <div x-show="toast" x-transition class="toast" style="background: #22c55e;"
         x-init="setTimeout(() => toast = '', 2000)" x-text="toast"></div>
  </div>

</body>
</html>

运行步骤

  1. 复制代码保存为 index.html
  2. 浏览器直接打开

预期输出

  • 点击标签页按钮切换不同框架介绍
  • 点击"打开详情"弹出模态框,点遮罩或取消关闭
  • 点击确认后弹绿色 Toast,2 秒后自动消失
  • 整个页面没有一行自定义 JS,全是 HTML 属性驱动

信息

路径
/tech-stacks/alpinejs/examples/Hello World - 标签页与模态框.md
更新时间
2026/5/30