创建主页面
二级路由的入口
<template><div>顶部通栏</div><div>顶部导航</div><div><!-- 二级路由出口 --><router-view></router-view></div><div>底部</div></template><script>export default {name: 'XtxLayout'}</script><style scoped lang='less'></style>
组件
将页面中的重复模块封装组件然后全部导入主页面
顶部通栏
需要在
public/index.html中引入字体图标文件
<link rel="icon" href="<%= BASE_URL %>favicon.ico"><link rel="stylesheet" href="//at.alicdn.com/t/font_2143783_iq6z4ey5vu.css"><title><%= htmlWebpackPlugin.options.title %></title>
<template><nav class="app-topnav"><div class="container"><ul><li><a href="javascript:;"><i class="iconfont icon-user"></i>周杰伦</a></li><li><a href="javascript:;">退出登录</a></li><li><a href="javascript:;">请先登录</a></li><li><a href="javascript:;">免费注册</a></li><li><a href="javascript:;">我的订单</a></li><li><a href="javascript:;">会员中心</a></li><li><a href="javascript:;">帮助中心</a></li><li><a href="javascript:;">关于我们</a></li><li><a href="javascript:;"><i class="iconfont icon-phone"></i>手机版</a></li></ul></div></nav></template><script>export default {name: 'AppTopnav'}</script><style scoped lang="less">.app-topnav {background: #333;ul {display: flex;height: 53px;justify-content: flex-end;align-items: center;li {a {padding: 0 15px;color: #cdcdcd;line-height: 1;display: inline-block;i {font-size: 14px;margin-right: 2px;}&:hover {color: @xtxColor;}}~ li {a {border-left: 2px solid #666;}}}}}</style>
根据当前的登录状态显示 用户名和退出登录
<ul><template v-if="$store.state.user.profile.token"><li><a href="javascript:;"><i class="iconfont icon-user"></i>周杰伦</a></li><li><a href="javascript:;">退出登录</a></li></template><template v-else><li><a href="javascript:;">请先登录</a></li><li><a href="javascript:;">免费注册</a></li></template></ul>
头部
<template><header class='app-header'><div class="container"><h1 class="logo"><RouterLink to="/">小兔鲜</RouterLink></h1><ul class="app-header-nav"><li class="home"><RouterLink to="/">首页</RouterLink></li><li><a href="#">美食</a></li><li><a href="#">餐厨</a></li><li><a href="#">艺术</a></li><li><a href="#">电器</a></li><li><a href="#">居家</a></li><li><a href="#">洗护</a></li><li><a href="#">孕婴</a></li><li><a href="#">服装</a></li><li><a href="#">杂货</a></li></ul><div class="search"><i class="iconfont icon-search"></i><input type="text" placeholder="搜一搜"></div><div class="cart"><a class="curr" href="#"><i class="iconfont icon-cart"></i><em>2</em></a></div></div></header></template><script>export default {name: 'AppHeader'}</script><style scoped lang='less'>.app-header {background: #fff;.container {display: flex;align-items: center;}.logo {width: 200px;a {display: block;height: 132px;width: 100%;text-indent: -9999px;background: url('~@/assets/images/logo.png') no-repeat center 18px / contain;}}.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;}}}.search {width: 170px;height: 32px;position: relative;border-bottom: 1px solid #e7e7e7;line-height: 32px;.icon-search {font-size: 18px;margin-left: 5px;}input {width: 140px;padding-left: 5px;color: #666;}}.cart {width: 50px;.curr {height: 32px;line-height: 32px;text-align: center;position: relative;display: block;.icon-cart{font-size: 22px;}em {font-style: normal;position: absolute;right: 0;top: 0;padding: 1px 6px;line-height: 1;background: @helpColor;color: #fff;font-size: 12px;border-radius: 10px;font-family: Arial;}}}}</style>
抽离模板中的header-nav组件,后面的顶部通栏需要复用,这里封装成组件 将当导航栏替换成该组件
<template><ul class="app-header-nav"><li class="home"><RouterLink to="/">首页</RouterLink></li><li><a href="#">美食</a></li><li><a href="#">餐厨</a></li><li><a href="#">艺术</a></li><li><a href="#">电器</a></li><li><a href="#">居家</a></li><li><a href="#">洗护</a></li><li><a href="#">孕婴</a></li><li><a href="#">服装</a></li><li><a href="#">杂货</a></li></ul></template><style scoped lang='less'>.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;}}}</style>
底部
<template><footer class="app_footer"><!-- 联系我们 --><div class="contact"><div class="container"><dl><dt>客户服务</dt><dd><i class="iconfont icon-kefu"></i> 在线客服</dd><dd><i class="iconfont icon-question"></i> 问题反馈</dd></dl><dl><dt>关注我们</dt><dd><i class="iconfont icon-weixin"></i> 公众号</dd><dd><i class="iconfont icon-weibo"></i> 微博</dd></dl><dl><dt>下载APP</dt><dd class="qrcode"><img src="@/assets/images/qrcode.jpg" /></dd><dd class="download"><span>扫描二维码</span><span>立马下载APP</span><a href="javascript:;">下载页面</a></dd></dl><dl><dt>服务热线</dt><dd class="hotline">400-0000-000 <small>周一至周日 8:00-18:00</small></dd></dl></div></div><!-- 其它 --><div class="extra"><div class="container"><div class="slogan"><a href="javascript:;"><i class="iconfont icon-footer01"></i><span>价格亲民</span></a><a href="javascript:;"><i class="iconfont icon-footer02"></i><span>物流快捷</span></a><a href="javascript:;"><i class="iconfont icon-footer03"></i><span>品质新鲜</span></a></div><!-- 版权信息 --><div class="copyright"><p><a href="javascript:;">关于我们</a><a href="javascript:;">帮助中心</a><a href="javascript:;">售后服务</a><a href="javascript:;">配送与验收</a><a href="javascript:;">商务合作</a><a href="javascript:;">搜索推荐</a><a href="javascript:;">友情链接</a></p><p>CopyRight © 小兔鲜儿</p></div></div></div></footer></template><script>export default {name: 'AppFooter'}</script><style scoped lang='less'>.app_footer {overflow: hidden;background-color: #f5f5f5;padding-top: 20px;.contact {background: #fff;.container {padding: 60px 0 40px 25px;display: flex;}dl {height: 190px;text-align: center;padding: 0 72px;border-right: 1px solid #f2f2f2;color: #999;&:first-child {padding-left: 0;}&:last-child {border-right: none;padding-right: 0;}}dt {line-height: 1;font-size: 18px;}dd {margin: 36px 12px 0 0;float: left;width: 92px;height: 92px;padding-top: 10px;border: 1px solid #ededed;.iconfont {font-size: 36px;display: block;color: #666;}&:hover {.iconfont {color: @xtxColor;}}&:last-child {margin-right: 0;}}.qrcode {width: 92px;height: 92px;padding: 7px;border: 1px solid #ededed;}.download {padding-top: 5px;font-size: 14px;width: auto;height: auto;border: none;span {display: block;}a {display: block;line-height: 1;padding: 10px 25px;margin-top: 5px;color: #fff;border-radius: 2px;background-color: @xtxColor;}}.hotline {padding-top: 20px;font-size: 22px;color: #666;width: auto;height: auto;border: none;small {display: block;font-size: 15px;color: #999;}}}.extra {background-color: #333;}.slogan {height: 178px;line-height: 58px;padding: 60px 100px;border-bottom: 1px solid #434343;display: flex;justify-content: space-between;a {height: 58px;line-height: 58px;color: #fff;font-size: 28px;i {font-size: 50px;vertical-align: middle;margin-right: 10px;font-weight: 100;}span {vertical-align: middle;text-shadow: 0 0 1px #333;}}}.copyright {height: 170px;padding-top: 40px;text-align: center;color: #999;font-size: 15px;p {line-height: 1;margin-bottom: 20px;}a {color: #999;line-height: 1;padding: 0 10px;border-right: 1px solid #999;&:last-child {border-right: none;}}}}</style>
接口数据渲染导航
import request from '@/utils/request'/*** 获取导航数据*/export const reqFindHeadCategory = () => request('/home/category/head', 'get')
在组件中调用接口讲数据渲染到组件中 首页数据接口中没有,自己手写一个
<ul class="app-header-nav"><li class="home"><RouterLink to="/">首页</RouterLink></li><li v-for="item in categoryList" :key="item.id"><RouterLink :to="`/category/${item.id}`">{{item.name}}</RouterLink></li></ul><script>import { ref } from 'vue'import { reqFindHeadCategory } from '@/api/home'export default {setup () {const categoryList = ref([])async function loadCategory () {const res = await reqFindHeadCategory()categoryList.value = res.result}loadCategory()return {categoryList}}}</script>
vuex 管理导航数据
导航栏的数据是通用的,使用vuex管理
import { reqFindHeadCategory } from '@/api/home'export default {namespaced: true,state: () => {return {list: []}},mutations: {setList (state, categoryList) {state.list = categoryList}},actions: {async getList (context) {const res = await reqFindHeadCategory()context.commit('setList', res.result)}}}
在首页发送请求 app-header-nav中使用computed获取vuex数据
export default {name: 'XtxLayout',components: {AppTopnav,AppHeader,AppFooter},setup () {const store = useStore()store.dispatch('category/getList')}}
export default {setup () {const store = useStore()const categoryList = computed(() => {return store.state.category.list})return {categoryList}}}
吸顶导航
<template><div class="app-header-sticky"><div class="container"><RouterLink class="logo" to="/" /><AppHeaderNav /><div class="right"><RouterLink to="/">品牌</RouterLink><RouterLink to="/">专题</RouterLink></div></div></div></template><script>import AppHeaderNav from './app-header-nav'export default {name: 'AppHeaderSticky',components: { AppHeaderNav }}</script><style scoped lang='less'>.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;}}}}</style>
监听dom 需要在 onMuounted 生命周期函数 监听 scroll
:class="{show:showFlag}"动态添加类名
setup () {const showFlag = ref('')onMounted(() => {window.addEventListener('scroll', () => {const scrollTop = document.documentElement.scrollTop// console.log(scrollTop)showFlag.value = scrollTop >= 78})})return {showFlag}}
插件重构导航逻辑
装包
npm i @vueuse/core@5.3.0插件网址:https://vueuse.org/core/usewindowscroll/
<template><div class="app-header-sticky" :class="{show:y >= 78}"><div class="container"><RouterLink class="logo" to="/" /><AppHeaderNav /><div class="right"><RouterLink to="/">品牌</RouterLink><RouterLink to="/">专题</RouterLink></div></div></div></template><script>import { useWindowScroll } from '@vueuse/core'import AppHeaderNav from './app-header-nav'export default {name: 'AppHeaderSticky',components: { AppHeaderNav },setup () {const { y } = useWindowScroll()// console.log('y', y)return {y}}}</script>
