📚 Nuxt 摄影项目(二):基础组件搭建 & 主题切换功能实现 & Nuxt UI 使用

83 阅读2分钟

📚 Nuxt 摄影项目(二):基础组件搭建 & 主题切换功能实现 & Nuxt UI 使用

本篇将继续搭建摄影网站的基础框架,主要内容包含:

  • 创建头部(Header)与底部(Footer)布局组件
  • 使用 Nuxt UI 的基础组件
  • 实现主题切换功能(浅色 / 深色 / 跟随系统)
  • 配置默认布局

🔗 系列文章导航

章节链接
(一)项目搭建juejin.cn/post/757213…
(二)基础组件 & 主题切换(当前)juejin.cn/post/757213…

🧱 1. 新增头部组件(Header)

创建文件:

app/components/layouts/header.vue

内容如下:

<script setup lang="js">
  import {useTheme} from "~/composables/useTheme.js";

  const route = useRoute()
  const themeInfo = ref(null)
  const colorMode = useColorMode()
  const {setDark, setLight, setSystem} = useTheme()

  const themes = ref([
    {icon: 'i-lucide-monitor', label: '跟随系统', value: 'system', setter: setSystem},
    {icon: 'i-lucide-sun', label: '浅色模式', value: 'light', setter: setLight},
    {icon: 'i-lucide-moon', label: '深色模式', value: 'dark', setter: setDark,}
  ])

  const themeList = computed(() =>
      themes.value.map(theme => ({
        ...theme,
        onSelect: () => {
          themeInfo.value = theme
          theme.setter()
        }
      }))
  )

  const menuItems = computed(() =>
      [
        {label: "首页 🏠", to: "/", active: route.path === '/'},
        {label: "画廊 🎨", to: "/gallery", active: route.path.startsWith('/gallery')},
        {label: "足迹 👣", to: "/map", active: route.path.startsWith('/map')},
        {label: "关于我 👴", to: "/about", active: route.path.startsWith('/about')},
      ]
  )

  onMounted(() => {
    themeInfo.value = themeList.value.find(theme => theme.value === colorMode.preference)
    console.log(themeList.value)
  })
</script>

<template>
  <UHeader>
    <template #title>
      LOGO
    </template>

    <UNavigationMenu :items="menuItems" type="single"/>

    <template #right>
      <UDropdownMenu v-if="themeInfo" :items="themeList">
        <UTooltip text="主题">
          <UButton
              :icon="themeInfo.icon" color="neutral" variant="ghost"/>
        </UTooltip>
      </UDropdownMenu>
    </template>
  </UHeader>
</template>

<style scoped lang="scss"></style>

🧱 2. 新增底部组件(Footer)

创建文件:

app/components/layouts/footer.vue

内容:

<script setup lang="js">
</script>

<template>
  <UFooter>
    版权所有 Copyright(©)2009-2022上海博卡软件科技有限公司
  </UFooter>
</template>

<style scoped lang="scss"></style>

🧱 3. 创建默认布局 Layout(default.vue)

创建文件:

app/layouts/default.vue

内容(注意路径是否与你实际一致):

<script setup lang="js">
  import Header from "~/components/base/Header.vue";
  import Footer from "~/components/base/Footer.vue";
</script>

<template>
  <UApp>
    <Header/>
    <UMain>
      <NuxtPage/>
      <Footer/>
    </UMain>
  </UApp>
</template>

<style scoped lang="scss"></style>

⚠️ 如果你的目录是 components/layouts,记得把路径修改为:
~/components/layouts/Header.vue


🧱 4. 修改根组件 app.vue

<template>
  <NuxtLayout>
    <NuxtPage/>
  </NuxtLayout>
</template>

保持默认即可。


🧱 5. 测试 Nuxt UI 组件是否工作正常

编辑:

app/pages/index.vue

内容:

<script setup lang="js"></script>

<template>
  <div class="component">
    <UButton>Button</UButton>
  </div>
</template>

<style scoped lang="scss"></style>

正常显示按钮说明 Nuxt UI 工作正常。


🧱 6. 实现主题切换逻辑(useTheme.js)

新增文件:

app/composables/useTheme.js

内容:

export function useTheme() {
    const colorMode = useColorMode()

    const setLight = () => {
        colorMode.preference = 'light'
    }
    const setDark = () => {
        colorMode.preference = 'dark'
    }
    const setSystem = () => {
        colorMode.preference = 'system'
    }

    return {setLight, setDark, setSystem,}
}

到此为止,主题切换已经可以完整工作 🎉


🎉 最终效果

image.png

你现在已经拥有:

✔ 一个全局头部(Header)
✔ 一个全局底部(Footer)
✔ 一个默认布局(default)
✔ 可正常显示的 Nuxt UI 组件
✔ 可切换浅色 / 深色 / 跟随系统 的主题功能

整个摄影网站的基础架构已经完成!