导航菜单栏结构和样式代码实现
一级导航栏
views/HomeView.vue
<template>
<div>
<Shortcut></Shortcut>
<Header></Header>
<div class="inner">
<Navigation></Navigation>
</div>
<div>
我是主页
</div>
</div>
</template>
<script setup>
import Shortcut from "@/components/common/Shortcut.vue"
import Header from "@/components/home/Header"
import Navigation from "@/components/home/Navigation"
</script>
<style lang="less" scoped>
.inner{
background-color: #f4f4f4;
}
</style>
src/components/home/navigation.vue
<template>
<div class="nav ">
<div class="main clearfix">
<div class="menu fl">
<LeftMenu></LeftMenu>
</div>
<div class="banner fl">我是banner</div>
</div>
</div>
</template>
<style lang="less" scoped>
.nav {
.main {
padding-top: 15px;
width: var(--content-width);
margin: 0 auto;
}
}
</style>
<script setup>
import LeftMenu from "./LeftMenu.vue";
</script>
src/components/home/leftmenu.vue
<template>
<div class="left-menu">
<ul>
<li>
<span>
<a href="">手机</a>
<span>/</span>
<a href="">运营商</a>
<span>/</span>
<a href="">数码</a>
</span>
</li>
</ul>
<div class="second-item">我是二级菜单</div>
</div>
</template>
<style scoped lang="less">
@red: #e2231a;
.left-menu {
// text-align: left;
// float: left;
background-color: #fff;
width: 190px;
height: 470px;
ul {
padding-top: 15px;
li {
padding-top: 5px;
padding-bottom: 5px;
padding-left: 15px;
&:hover {
cursor: pointer;
background-color: #d9d9d9;
}
a {
font-size: 14px;
color: #333;
&:hover {
cursor: pointer;
color: @red;
}
}
}
}
}
</style>
导航菜单栏接口数据渲染
数据库存储格式
let leftMenuData=ref([])
onMounted(()=>{
getMainMenu().then(res=>{
console.log(res.data)
init_menu_data(res.data)
})
})
根据main_menu_id判断菜单名在哪一行
const init_menu_data=(menuData=>{
for(let i in menuData){
let jsonData = JSON.parse(menuData[i])
leftMenuData.value.push(jsonData)
}
console.log(leftMenuData)
})
// 接口返回数据需要进行加工,基本结构应该是[{index:1,data:[{name,url},{},{}]}]
const showMainData=computed(()=>{
let resultList = [];
let result = {"index":"","data":[]};
for(let i in leftMenuData.value){
let id = leftMenuData.value[i].main_menu_id;
let data = {"name":leftMenuData.value[i].main_menu_name};
if(result["index"] != null && id == result["index"]){
result["data"].push(data);
}else{
result = {"index":"","data":[]};
result["index"] = id;
result["data"].push(data);
resultList.push(result);
}
}
return resultList;
})
完整代码
<template>
<div class="left-menu">
<ul>
<li v-for="(item,index) in showMainData" :key="index">
<span v-for="(d,i) in item.data" :key="i">
<a href="">{{d.name}}</a>
<!-- 删除多余的斜线 -->
<span v-if="item.data.length-i-1">/</span>
</span>
</li>
</ul>
<div class="second-item">我是二级菜单</div>
</div>
{{showMainData}}
</template>
<style scoped lang="less">
@red: #e2231a;
.left-menu {
// text-align: left;
// float: left;
background-color: #fff;
width: 190px;
height: 470px;
ul {
padding-top: 15px;
li {
padding-top: 5px;
padding-bottom: 5px;
padding-left: 15px;
&:hover {
cursor: pointer;
background-color: #d9d9d9;
}
a {
font-size: 14px;
color: #333;
&:hover {
cursor: pointer;
color: @red;
}
}
}
}
}
</style>
<script setup>
import {getMainMenu} from "@/network/home.js"
import {onMounted, ref,computed} from "vue"
let leftMenuData=ref([])
onMounted(()=>{
getMainMenu().then(res=>{
init_menu_data(res.data)
})
})
const init_menu_data=(menuData=>{
for(let i in menuData){
let jsonData = JSON.parse(menuData[i])
leftMenuData.value.push(jsonData)
}
})
// 接口返回数据需要进行加工,基本结构应该是[{index:1,data:[{name,url},{},{}]}]
const showMainData=computed(()=>{
let resultList = [];
let result = {"index":"","data":[]};
for(let i in leftMenuData.value){
let id = leftMenuData.value[i].main_menu_id;
let data = {"name":leftMenuData.value[i].main_menu_name};
if(result["index"] != null && id == result["index"]){
result["data"].push(data);
}else{
result = {"index":"","data":[]};
result["index"] = id;
result["data"].push(data);
resultList.push(result);
}
}
return resultList;
})
</script>
二级菜单栏的显示与隐藏
需要把二级菜单调到右边覆盖banner
home/leftMenu.vue
home/SecondMenu.vue
接收一级菜单传递过来的id
<template>
<div>我是二级菜单xxxxxxxxxxxxxxxxxx {{showSecondMenuIndex}}</div>
</template>
<script setup>
const showSecondMenuIndex = defineProps(["showSecondMenuIndex"])
</script>
鼠标移动会向二级菜单传递一级菜单的ID
二级菜单栏的代码开发骨架结构搭建
home/SecondMenu.vue
<template>
<div class="second">
<div class="menu-content">
<div class="menu-title">
<span>
<a href=""> 家电馆
<img src="@/assets/images/menu/arrows-white.png" alt="" />
</a>
</span>
</div>
<div class="menu-detail">
<div class="menu-detail-item">
<span>
<span>
<span class="menu-detail-tit">
<a href="">电视
<img src="@/assets/images/menu/arrows-black.png" alt="" />
</a>
</span>
<span class="menu-detail-data">
<a href="">全面屏电视</a>
</span>
</span>
</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
const showSecondMenuIndex = defineProps(["showSecondMenuIndex"]);
</script>
<style lang="less" scoped>
</style>
二级菜单栏的代码开发页面样式渲染
<template>
<div class="second">
<div class="menu-content">
<div class="menu-title">
<span>
<a href="">
家电馆
<img src="@/assets/images/menu/arrows-white.png" alt="" />
</a>
</span>
</div>
<div class="menu-detail">
<div class="menu-detail-item">
<span>
<span class="menu-detail-tit">
<a href=""
>电视
<img src="@/assets/images/menu/arrows-black.png" alt="" />
</a>
</span>
<span class="menu-detail-data">
<a href="">全面屏电视</a>
</span>
</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
const showSecondMenuIndex = defineProps(["showSecondMenuIndex"]);
</script>
<style lang="less" scoped>
@red: #e2231a;
.second {
width: 1000px;
background-color: #fff;
border: 2px solid #e9e9e9;
padding: 20px;
.menu-content {
margin-right: 900px;
.menu-title {
a {
display: inline-block;
background-color: black;
color: white;
margin-right: 10px;
height: 25px;
line-height: 25px;
padding: 0 10px;
img {
height: 18px;
}
&:hover {
background-color: @red;
}
}
}
.menu-detail {
margin-top: 15px;
.menu-detail-item {
.menu-detail-tit {
a {
font-weight: 700;
img {
height: 18px;
}
&:hover {
color: @red;
}
}
}
.menu-detail-data {
a {
margin-left: 20px;
&:hover {
color: @red;
}
}
}
}
}
}
}
</style>
二级菜单栏的接口数据渲染
home/secondMenu.vue
<template>
<div class="second">
<div class="menu-content" v-for="(item,index) in showSubMenuData" :key="index">
<div class="menu-title">
<span v-for="(d,i) in item.data" :key="i">
<a href="" v-show="d.type==='channel'">
{{d.name}}
<img src="@/assets/images/menu/arrows-white.png" alt="" />
</a>
</span>
</div>
<div class="menu-detail">
<div class="menu-detail-item">
<span v-for="(d,i) in item.data" :key="i">
<span class="menu-detail-tit" v-if="d.type==='dt'">
<a href=""
>{{d.name}}
<img src="@/assets/images/menu/arrows-black.png" alt="" />
</a>
</span>
<span class="menu-detail-data" v-else-if="d.type==='dd'">
<a href="">{{d.name}}</a>
</span>
</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { getSecondMenu } from "@/network/home.js";
import { ref, watch,computed } from "vue";
const showSecondMenuIndex = defineProps(["showSecondMenuIndex"]);
watch(showSecondMenuIndex, (newVlue, oldValue) => {
getSecondMenu(newVlue.showSecondMenuIndex).then((res) => {
initMenuData(res.data);
});
});
let subMenuData = ref([]);
const initMenuData = (menuData) => {
// 每次初始化的时候 必须把subMenuData设置为空 不然数据会累加
subMenuData.value = [];
for (let i in menuData) {
let jsonData = JSON.parse(menuData[i]);
subMenuData.value.push(jsonData);
}
};
const showSubMenuData = computed(() => {
let resultList = [];
let result = { index: "", data: [] };
for (let i in subMenuData.value) {
let id = subMenuData.value[i].sub_menu_id;
let data = {
name: subMenuData.value[i].sub_menu_name,
type: subMenuData.value[i].sub_menu_type,
};
if (result["index"] != null && id == result["index"]) {
result["data"].push(data);
} else {
result = { index: "", data: [] };
result["index"] = id;
result["data"].push(data);
resultList.push(result);
}
}
return resultList;
});
</script>
<style lang="less" scoped>
@red: #e2231a;
.second {
width: 1000px;
background-color: #fff;
border: 2px solid #e9e9e9;
padding: 20px;
.menu-content {
// margin-right: 80px;
.menu-title {
a {
display: inline-block;
background-color: black;
color: white;
margin-right: 10px;
height: 25px;
line-height: 25px;
padding: 0 10px;
img {
height: 18px;
}
&:hover {
background-color: @red;
}
}
}
.menu-detail {
margin-top: 15px;
.menu-detail-item {
.menu-detail-tit {
a {
font-weight: 700;
img {
height: 18px;
}
&:hover {
color: @red;
}
}
}
.menu-detail-data {
a {
margin-left: 20px;
&:hover {
color: @red;
}
}
}
}
}
}
}
</style>
首页 Banner 图效果开发
home/banner
<template>
<div class="block" style="width: 1000px;">
<span class="demonstration"></span>
<el-carousel trigger="click" height="470px">
<el-carousel-item v-for="item in images" :key="item">
<img :src="item" alt="">
</el-carousel-item>
</el-carousel>
</div>
</template>
<script setup>
import banner1 from "@/assets/images/banner/banner1.png";
import banner2 from "@/assets/images/banner/banner2.png";
import banner3 from "@/assets/images/banner/banner3.png";
import banner4 from "@/assets/images/banner/banner4.png";
import banner5 from "@/assets/images/banner/banner5.png";
import banner6 from "@/assets/images/banner/banner6.png";
import { ref } from "vue";
const images=ref([
banner1,
banner2,
banner3,
banner4,
banner5,
banner6
])
</script>
<style scoped>
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 150px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n + 1) {
background-color: #d3dce6;
}
</style>
home/Navigation.vue
<template>
<div class="nav ">
<div class="main clearfix">
<div class="menu fl">
<LeftMenu></LeftMenu>
</div>
<div class="banner fl"><Banner></Banner></div>
</div>
</div>
</template>
<style lang="less" scoped>
.nav {
.main {
padding-top: 15px;
width: var(--content-width);
margin: 0 auto;
}
}
</style>
<script setup>
import LeftMenu from "./LeftMenu.vue";
import Banner from "./Banner.vue";
</script>