Nuxt3-layout实战

666 阅读3分钟

背景

在最近写的文章中,有小伙伴可能搞不明白,Nuxt3中 怎么去设计自己的Layout 导致在写代码的时候,可能很困惑, 今天用一个实际的案例讲解一下

我们以官网为例,有基本的布局, 有登录,有菜单等

image.png

问题

他们疑惑的3个问题是:

  • 这样的layout 应该怎么写,代码怎么组织?
  • 菜单的高亮怎么处理?
  • 登录,退出 逻辑应该写在哪里,layout还是具体的页面?

实现1:layout怎么写

应该在 layouts 目录中创建一个新的 layout, 如果项目比较简单,那就创建一个 default.vue 作为默认的layout

区别在于: default.vue这个layout 在写页面的时候,是不用指定 NuxtLayoutname

如果项目比较大,会存在多个layout的情况,我们这里创建一个新的, layout-3.vue

layouts/layout-3.vue

<template>
  <div>
    <top-header></top-header>
    
    <div class="main-container">
      <slot></slot>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.main-container {
  max-width: 1000px;
  margin-left: auto;
  margin-right: auto;
}
</style>

layout的问题已经解决了, 现在增加 顶部菜单组件

Nuxt3中写在 根目录 里面的 components 目录里面的组件是全局组件, 所以这里没有 引入 top-header 这个文件

/components/top-header.vue

<template>
  <div class="top-header">
    <div class="header-layout">
      <div class="menu-list">
        <div
          class="menu-item"
          :class="{ 'active-menu-item': isActive === index }"
          v-for="(item, index) in menuList"
          :key="index"
        >
          <NuxtLink :to="item.to">{{ item.text }}</NuxtLink>
        </div>
      </div>
      <div class="logout" @click="onLogin">{{ isLogin ? '退出' : '登录' }}</div>
    </div>
  </div>
</template>

<script setup>
const route = useRoute()
const useToken = useCookie('token')

const isLogin = computed(() => {
  return useToken.value
})

const isActive = computed(() => {
  let index = menuList.value.findIndex((item) => item.to === route.path)

  return index
})

const menuList = ref([
  {
    text: '功能',
    to: '/page-header/function'
  },
  {
    text: '解决方案',
    to: '/page-header/solution'
  },
  {
    text: '资源',
    to: '/page-header/resource'
  }
])

const onLogin = () => {
  if (!useToken.value) {
    // 模拟登录
    useToken.value = Date.now()
  } else {
    // 模拟退出
    useToken.value = ''
  }
}
</script>

<style lang="scss" scoped>
.top-header {
  background-color: #000;
  display: flex;
  justify-content: center;
  align-items: center;

  font-size: 14px;
  font-weight: 500;
  height: 68px;

  .menu-list {
    flex: 1;
    flex-shrink: 0;

    display: flex;
    justify-content: center;
    gap: 20px;
  }

  a {
    text-decoration: none;
    color: #fff;
  }

  .active-menu-item {
    a {
      color: #cb5a9c;
    }
  }
}

.header-layout {
  max-width: 1000px;
  flex: 1;
  display: flex;
  justify-content: space-between;
}

.logout {
  color: #fff;
  cursor: pointer;
}
</style>

实现2:菜单高亮怎么处理

上面代码,已经看到了,菜单的高亮是拿到当前的path, 去匹配这个path 就设置了菜单的高亮

我们从 “功能”页面切换到 “解决方案” 页面, 是完整的页面切换,所有,在切换过去,isActive会重新执行; 这样就实现了菜单的高亮。

实现3:登录登出逻辑怎么写

需要借助 cookie 或者 localStorage 或者 sessionStorage 去判断登录状态; 当然这里做的比较基础,已经能最小化处理了,登录,退出 的一些逻辑问题

所以登录,退出逻辑是写在 top-header组件里面的; 当然事件项目中会有调用接口,逻辑判断,浏览器 Storage或者 cookie中的数据清空操作。

页面代码

我们看看具体的页面,以 pages/page-header/function.vue 功能页面为例

<template>
  <NuxtLayout name="layout-3">
    <div class="page-container">功能页面</div>
  </NuxtLayout>
</template>

<script setup></script>

<style lang="scss" scoped>
.page-container {
  background-color: pink;
}
</style>

目录结构

- components
    - top-header.vue
- pages/
    - page-header/
        - index.vue
        - function.vue
        - resource.vue
        - solution.vue
- layouts/
    - layout-3.vue
- package.json

上面从 layout的创建, 布局编写, 登录,退出 逻辑组织 完整的引导了一个新手掌握 layout;

希望对各位Nuxt3新手看官有帮助~ 蟹蟹 😊😊😊