提醒
本文实例使用vue开发的
一、需求场景
开发商品分类页面需求如下:
- 顶部显示商品分类导航栏,可左右自由滑动,点击左边或右边未显示完整的tab自动滚动显示完整;
- 点击顶部显示商品分类导航栏tab,下面列表数据显示对应的分类商品(SKU);
二、需求分析
- 顶部显示商品分类导航栏是分类数量是可变的;
- 需要计算tab距离父级布局左边和右边的距离 ,以此判断点击的分类tab是否显示完整。
- 点击顶部显示商品分类导航栏tab更新下面列表数据;
三、技术方案
- vue是数据绑定的,使用v-for,示例代码:
v-for="(item, index) in tabList:key="index
- 使用getBoundingClientRect()方法,获取元素的位置以及其他相关信息。
四、实例效果图
最右边tab未显完整
点击后自动滚动并显示完整
五、实例代码
testTab.vue文件代码
<template>
<div class="content-wrap">
<div class="tool-bar">
<div class="tool-bar-back">返回</div>
<div class="tool-bar-title">热销商品</div>
</div>
<div id="navTab" class="nav-tab-wrap">
<div class="tabs-btn" id="navTabs">
<div style="padding-right: 0.16rem;" v-for="(item, index) in tabList" :key="index"
:id="'tabItem' + item.id" @click="swithtab(item.id)">
<div class="item" :class="{ 'item-active': tabId == item.id }">
{{ item.name }}
</div>
</div>
</div>
<div id="list" class="list-wrap" v-for="(item, index) in skuList" :key="index">
<div class="list-item-wrap">
<div class="list-item-name">{{ item.name }}</div>
<div class="list-item-desc">{{ item.desc }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
typeData: [
{
id: "0",
name: "水果",
skuList: [{
skuId: "123000",
name: "哈密瓜",
desc: "新鲜水果,果汁甜"
},
{
skuId: "123001",
name: "苹果",
desc: "新鲜水果,红苹果"
},
{
skuId: "123002",
name: "葡萄",
desc: "新鲜水果,紫色圆圆"
},
{
skuId: "123003",
name: "火龙果",
desc: "新鲜水果,果汁甜"
},
{
skuId: "123004",
name: "蓝莓",
desc: "新鲜水果,有护眼功效"
}
]
},
{
id: "1",
name: "蔬菜",
skuList: [{
skuId: "223000",
name: "西红柿",
desc: "新鲜蔬菜,健康"
},
{
skuId: "223001",
name: "西芹",
desc: "新鲜蔬菜,健康"
},
{
skuId: "223002",
name: "娃娃菜",
desc: "新鲜蔬菜"
},
{
skuId: "223003",
name: "四季豆",
desc: "新鲜蔬菜,"
},
{
skuId: "223004",
name: "胡萝卜",
desc: "新鲜,有机蔬菜"
}
]
},
{
id: "2",
name: "肉类",
skuList: [
{
skuId: "223003",
name: "牛腱",
desc: "新鲜牛肉"
},
{
skuId: "223004",
name: "五花肉",
desc: "新鲜猪肉"
},
],
},
{
id: "3",
name: "粮油",
skuList: [
{
skuId: "323003",
name: "花生油",
desc: "炒菜香"
},
],
},
{
id: "4",
name: "居家用品",
skuList: [
{
skuId: "423003",
name: "高压锅",
desc: "安全,使用级别"
},
{
skuId: "423003",
name: "炒锅",
desc: "不粘锅"
},
],
},
{
id: "5",
name: "饮品",
skuList: [
{
skuId: "523003",
name: "有机纯牛奶",
desc: "高蛋白质"
},
{
skuId: "523004",
name: "雪碧",
desc: "碳酸饮料"
},
],
}
],
tabList: [],
skuList: [],
tabId: 0,
}
},
mounted() {
this.initData()
},
methods: {
initData() {
this.tabList = this.typeData
this.skuList = this.typeData[this.tabId].skuList;
},
swithtab(id) {
let navTabsDiv = document.getElementById("navTabs")
let navTabItemDiv = document.getElementById(`tabItem${id}`)
let navTabsRect = navTabsDiv.getBoundingClientRect()
let navTabItemRect = navTabItemDiv.getBoundingClientRect()
if (navTabItemRect.left < 36) {
navTabsDiv.scrollBy(-(navTabsRect.left - navTabItemRect.left + 40), 0)
} else if (navTabItemRect.right > navTabsRect.right) {
if (id == this.tabList.length - 1) {
navTabsDiv.scrollBy(navTabItemRect.right - navTabsRect.right, 0)
} else {
navTabsDiv.scrollBy(navTabItemRect.right - navTabsRect.right + 40, 0)
}
}
this.tabId = id;
this.skuList = this.typeData[id].skuList;
},
}
}
</script>
<style scoped lang="scss">
.content-wrap {
background-color: #f5f5f5;
}
.tool-bar {
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: row;
width: 100%;
height: 88px;
line-height: 88px;
font-size: 16px;
color: black;
align-items: flex-end;
background-color: #fff;
z-index: 9999;
}
.tool-bar-back {
width: 44px;
height: 88px;
line-height: 88px;
text-align: center;
margin-left: 16px;
align-items: center;
}
.tool-bar-title {
flex: 1;
font-weight: bold;
margin-right: 60px;
align-items: center;
text-align: center;
}
.nav-tab-wrap {
width: 3.43rem;
background: #FFF;
border-radius: 8px;
margin: .16rem auto 0;
padding-top: .16rem;
min-height: 6.5rem;
}
::-webkit-scrollbar {
height: 0;
}
.tabs-btn {
padding: 0 .16rem;
margin-top: .16rem;
overflow-x: scroll;
overflow-y: hidden;
display: flex;
padding-bottom: 16px;
border-bottom: #eee solid 1px;
.item {
padding: .05rem .12rem;
font-size: .14rem;
line-height: .2rem;
font-weight: 400;
color: #333333;
background: #f5f5f5;
border-radius: .15rem;
white-space: nowrap;
}
.item-active {
font-weight: 600;
color: #FFFFFF;
background: #FF594A;
}
}
.list-wrap {
position: relative;
display: flex;
flex-direction: column;
border-radius: 8px;
background-color: white;
margin-top: 16px;
overflow-y: scroll;
}
.list-item-wrap {
display: flex;
flex-direction: column;
padding: 10px;
align-items: flex-start;
flex: 1;
border-bottom: #eee solid 1px;
}
.list-item-name {
font-size: 14px;
font-weight: bold;
color: black;
}
.list-item-desc {
font-size: 12px;
color: black;
margin-top: 8px;
}
</style>