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

发布于:2025-05-19 ⋅ 阅读:(18) ⋅ 点赞:(0)

🖤 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">
                    <div
                        v-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">
        <div
            class="absolute inset-0 z-0 bg-[url(@/assets/showcase-bg.png)] bg-center bg-no-repeat opacity-20" />
        <div
            class="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">
            <div
                v-for="item in projectList"
                :key="item.id"
                class="relative overflow-hidden rounded-lg">
                <div>
                    <img :src="item.image" :alt="item.title" />
                </div>

                <div
                    class="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」


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


网站公告

今日签到

点亮在社区的每一天
去签到