ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

vue3 之 商城项目—layout静态模版结构搭建

2026/8/16 10:53:17 拓冰建站 浏览量
vue3 之 商城项目—layout静态模版结构搭建

layout—模块静态模版搭建

一般情况下我们会有nav区域,header区域,二级路由出口区域以及footer区域,如图
在这里插入图片描述
我们在开发的时候先把大模块搭建起来,再一步一步填充小模块

在layout下建文件,目录如下
在这里插入图片描述

在index.vue中把上面文件引入进来

<script setup>
import LayoutNav from './components/LayoutNav.vue'
import LayoutHeader from './components/LayoutHeader.vue'
import LayoutFooter from './components/LayoutFooter.vue'
</script><template><LayoutNav /><LayoutHeader /><RouterView /><LayoutFooter />
</template>

layout—字体图标引入

阿里的字体图标库支持多种引入方式,项目里采用的是font-class引用的方式
index.html

  <link rel="stylesheet" href="//at.alicdn.com/t/font_2143783_iq6z4ey5vu.css">

layout— 一级导航渲染

在这里插入图片描述
apis/layout.js

//导入封装好的http请求 可以看上一章发布的内容项目起步
import httpInstance from "@/utils/http"
export function getCategoryAPI () {return httpInstance({url: '/home/category/head'})
}

layout/layoutHeader

<script setup>import { getCategoryAPI } from '@/apis/layout'import { onMounted, ref } from 'vue'const categoryList = ref([])const getCategory = async () => {const res = await getCategoryAPI()categoryList.value = res.result}onMounted(() => getCategory())</script><template><header class='app-header'><div class="container"><h1 class="logo"><RouterLink to="/">小兔鲜</RouterLink></h1><ul class="app-header-nav"><li class="home" v-for="item in categoryList" :key="item.id"><RouterLink to="/">{{ item.name }}</RouterLink></li></ul><div class="search"><i class="iconfont icon-search"></i><input type="text" placeholder="搜一搜"></div><!-- 头部购物车 --></div></header>
</template>

layout—吸顶导航交互实现

需求:浏览器在上下滚动的过程中,如果距离顶部的滚动距离大于78px,吸顶导航显示,小于78px隐藏
在这里插入图片描述
安装vueuse插件

npm i @vueuse/core
//用里面的useScorll来解决滚动问题

layout/components/layoutFixed.vue

<script setup>
import LayoutHeaderUl from './LayoutHeaderUl.vue'
// vueUse
import { useScroll } from '@vueuse/core'
const { y } = useScroll(window)
</script>
<template><div class="app-header-sticky" :class="{ show: y > 78 }"><div class="container"><RouterLink class="logo" to="/" /><!-- 导航区域 --><ul class="app-header-nav "><li class="home"><RouterLink to="/">首页</RouterLink></li><li><RouterLink to="/">居家</RouterLink></li><li><RouterLink to="/">美食</RouterLink></li><li><RouterLink to="/">服饰</RouterLink></li><li><RouterLink to="/">母婴</RouterLink></li><li><RouterLink to="/">个护</RouterLink></li><li><RouterLink to="/">严选</RouterLink></li><li><RouterLink to="/">数码</RouterLink></li><li><RouterLink to="/">运动</RouterLink></li><li><RouterLink to="/">杂项</RouterLink></li></ul><div class="right"><RouterLink to="/">品牌</RouterLink><RouterLink to="/">专题</RouterLink></div></div></div>
</template><style scoped lang='scss'>
.app-header-sticky {width: 100%;height: 80px;position: fixed;left: 0;top: 0;z-index: 999;background-color: #fff;border-bottom: 1px solid #e4e4e4;// 此处为关键样式!!!// 状态一:往上平移自身高度 + 完全透明transform: translateY(-100%);opacity: 0;// 状态二:移除平移 + 完全不透明&.show {transition: all 0.3s linear;transform: none;opacity: 1;}.container {display: flex;align-items: center;}.logo {width: 200px;height: 80px;background: url("@/assets/images/logo.png") no-repeat right 2px;background-size: 160px auto;}.right {width: 220px;display: flex;text-align: center;padding-left: 40px;border-left: 2px solid $xtxColor;a {width: 38px;margin-right: 40px;font-size: 16px;line-height: 1;&:hover {color: $xtxColor;}}}
}.app-header-nav {width: 820px;display: flex;padding-left: 40px;position: relative;z-index: 998;li {margin-right: 40px;width: 38px;text-align: center;a {font-size: 16px;line-height: 32px;height: 32px;display: inline-block;&:hover {color: $xtxColor;border-bottom: 1px solid $xtxColor;}}.active {color: $xtxColor;border-bottom: 1px solid $xtxColor;}}
}
</style>

layout/index.vue

//导入
import LayoutFixed from './components/LayoutFixed.vue'

layout— Pinia优化重复请求

项目中有两种导航,一种普通导航一种吸顶导航
在这里插入图片描述
在这里插入图片描述
stores/category.js

import { ref } from 'vue'
import { defineStore } from 'pinia'
import { getCategoryAPI } from '@/apis/layout'
export const useCategoryStore = defineStore('category', () => {// 导航列表的数据管理// state 导航列表数据const categoryList = ref([])// action 获取导航数据的方法const getCategory = async () => {const res = await getCategoryAPI()categoryList.value = res.result}return {categoryList,getCategory}
})

layout/index.vue

// 触发获取导航列表的actionimport { useCategoryStore } from '@/stores/categoryStore'
import { onMounted } from 'vue'const categoryStore = useCategoryStore()onMounted(() => categoryStore.getCategory())

layout/components/layoutNav

// 触发获取导航列表的action
<script setup>
import { useCategoryStore } from '@/stores/categoryStore'
const categoryStore = useCategoryStore()
</script><template><ul class="app-header-nav"><li class="home"><RouterLink to="/">首页</RouterLink></li><li class="home" v-for="item in categoryStore.categoryList" :key="item.id"><RouterLink active-class="active" :to="`/category/${item.id}`">{{ item.name }}</RouterLink></li></ul>
</template><style lang="scss">
.app-header-nav {width: 820px;display: flex;padding-left: 40px;position: relative;z-index: 998;li {margin-right: 40px;width: 38px;text-align: center;a {font-size: 16px;line-height: 32px;height: 32px;display: inline-block;&:hover {color: $xtxColor;border-bottom: 1px solid $xtxColor;}}.active {color: $xtxColor;border-bottom: 1px solid $xtxColor;}}
}
</style>