当前位置: 首页 > news >正文

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | 页面布局 与 Vue Router 路由配置

🖤 Build Daily. Build Differently.

今天我们将基于的 Vue3 + TailwindCSS 项目,进一步拆分页面结构,引入 Vue Router,构建基础导航与页面路由体系。

仓库地址:https://github.com/SunACong/50-vue-projects


🧩 1. 页面结构设计

我们的页面将包含以下几个主要模块:

  • 🔗 Nav:导航栏组件,链接各个页面
  • 🏠 Home:首页介绍
  • 📦 Projects:展示 50 个项目列表
  • ℹ️ About:关于本站与项目介绍

📁 2. 创建组件结构

├── src
│   └── sections
│   	├── Nav.vue
│       ├── Home.vue
│       ├── Projects.vue
│       └── About.vue (未完成)
│   └── router
│   	├── index.js
│   └── constants
│   	├── index.js
│   └── assets
│   	├── logo.png 
│   	├── ...其他静态文件

你可以在仓库的对应文件夹下面找到所需要的静态文件:50days50projects

💻 3. 代码

Nav.vue

<template><header class="fixed top-0 right-0 left-0 z-50 bg-black/90"><div class="mx-auto max-w-7xl"><div class="c-space flex items-center justify-end py-5"><div class="mr-auto flex items-center justify-center gap-2"><img class="h-20 w-20" src="@/assets/logo.png" alt="" /></div><div class="flex items-center justify-center gap-10"><divv-for="item in navList":key="item.id"@click="currentTab = item.id":class="['font-mono text-gray-200 transition-all hover:scale-105',currentTab === item.id ? 'border-b-2 border-blue-400' : 'border-b-0',]"><a :href="item.link" @click="goHome">{{ item.title }}</a></div></div></div></div></header>
</template><script setup>import { ref } from 'vue'import { navList } from '../constants/index'const currentTab = ref(1)
</script>

Home.vue

<template><section class="flex min-h-screen w-full flex-col" id="Home"><divclass="absolute inset-0 z-0 bg-[url(@/assets/showcase-bg.png)] bg-center bg-no-repeat opacity-20" /><divclass="c-space z-1 mx-auto mt-30 flex w-full flex-col gap-y-20 text-center font-mono font-medium text-gray-200 sm:mt-60"><p class="text-2xl sm:text-3xl">50 天 50 个项目<span class="waving-hand">👋</span></p><p class="head-text">50 个独特的迷你项目来提升你的 HTML、CSS 和 JavaScript 技能</p><button class="btn border-2 font-mono">🚀让我们开始吧!🚀</button></div></section>
</template><script setup></script><style scoped>.waving-hand {animation-name: wave-animation;animation-duration: 2.5s;animation-iteration-count: infinite;transform-origin: 70% 70%;display: inline-block;}@keyframes wave-animation {0% {transform: rotate(0deg);}10% {transform: rotate(14deg);}20% {transform: rotate(-8deg);}30% {transform: rotate(14deg);}40% {transform: rotate(-4deg);}50% {transform: rotate(10deg);}60% {transform: rotate(0deg);}100% {transform: rotate(0deg);}}
</style>

Projects.vue

<template><section class="c-space" id="Projects"><div class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5"><divv-for="item in projectList":key="item.id"class="relative overflow-hidden rounded-lg"><div><img :src="item.image" :alt="item.title" /></div><divclass="absolute inset-0 flex flex-col items-center justify-center bg-black/70 font-mono opacity-0 transition-opacity duration-300 ease-in-out hover:opacity-100"><h3 class="mb-4 text-xl font-bold text-white">{{ item.title }}</h3><RouterLink:to="item.link"class="rounded-md bg-blue-500 px-4 py-2 text-white transition-colors duration-200 hover:bg-blue-600">Live Demo</RouterLink></div></div></div></section>
</template><script setup>import { projectList } from '../constants'
</script><style scoped></style>

src/router/index.js

import { createWebHistory, createRouter } from 'vue-router'import ExpandingCards from '@/projects/ExpandingCards.vue'const routes = [{path: '/',name: 'Home',component: () => import('@/sections/Home.vue')},{path: '/Projects',name: 'Projects',component: () => import('@/sections/Projects.vue')}
]const router = createRouter({history: createWebHistory(),routes,
})export default router

App.vue

<template><section class="max-w-8xl mx-auto"><router-view v-if="$route.path !== '/'"></router-view><template v-else><Navbar /><Home /><Projects /></template></section>
</template><script setup>import Navbar from './sections/Navbar.vue'import Home from './sections/Home.vue'import Projects from './sections/Projects.vue'
</script>

main.js

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'createApp(App).use(router).mount('#app')

src/constants/index.js

export const navList = [{ id: 1, title: 'Home', link: '#Home' },{ id: 2, title: 'Peoject', link: '#Projects' },{ id: 3, title: 'About', link: '#About' },
]export const projectList = []

✅ 4. 当前完成状态

  • Nav组件完成(包含导航链接)
  • Home组件完成(展示欢迎语与介绍)
  • Projects组件完成(展示项目概览)
  • About组件待完成
  • Router配置完成并接入 App.vue

🚀 小结

本日我们构建了基础页面架构与 Vue Router 路由系统,为后续页面跳转与模块拆分打下基础。

📅 下篇预告:开发 Day01 的组件内容「Expanding Cards」


🧠 页面是外壳,逻辑是灵魂。步步为营,才能无懈可击。

相关文章:

  • linux下编写shell脚本一键编译源码
  • LG P9844 [ICPC 2021 Nanjing R] Paimon Segment Tree Solution
  • java集合相关的api-总结
  • ElasticSearch-集群
  • 如何用mockito+junit测试代码
  • 图像定制大一统?字节提出DreamO,支持人物生成、 ID保持、虚拟试穿、风格迁移等多项任务,有效解决多泛化性冲突。
  • 【网络】Wireshark练习3 analyse DNS||ICMP and response message
  • LLM笔记(八)Transformer学习
  • Java八股文——Java基础篇
  • GBS 8.0服装裁剪计划软件在线试用
  • mac下载mysql
  • 选择之困:如何挑选合适的 Python 环境与工具——以 Google Colaboratory 为例
  • Mlp-Mixer-BiGRU故障诊断的python代码合集
  • 2025抓包工具Reqable手机抓包HTTPS亲测简单好用-快速跑通
  • 互联网大厂Java面试:从Spring Boot到微服务架构的深度探讨
  • 协程:单线程并发开发的高效利器
  • 谷歌官网下载谷歌浏览器设置中文
  • 使用Redission来实现布隆过滤器
  • C++ asio网络编程(8)处理粘包问题
  • Ubuntu---omg又出bug了
  • 最高法:依法惩治损害民营企业合法权益的串通投标行为
  • 旅马大熊猫“福娃”“凤仪”平安回国
  • 山东茌平民企巨头实控人省外再出手:斥资16亿拿下山西一宗探矿权
  • 蔡建忠已任昆山市副市长、市公安局局长
  • 《风林火山》千呼万唤始出来,戛纳首映后口碑崩盘?
  • 泽连斯基:俄代表团级别低,没人能做决定