示例:
1.分析分类页的结构,左边是scroll-view滚动视图,右边是楼层,初次加载页面,发请求获取一级分类,并渲染在侧边栏,分析数据,再渲染到右边main区,为二级子类。
2.此时右边展现的是第一个分类的死数据,定义计算属性,用索引返回一级分类,渲染右边main,此时依然是死数据。
3.设置点击事件,点击时获取index,将index定义后丢给计算属性,此时数据变活。左右完成联动。
<template>
<view>
<!-- 搜索 -->
<search />
<!-- 分类 -->
<view class="category">
<!-- 顶级分类 -->
<view class="sup">
<scroll-view scroll-y>
<text
v-for="(item, index) in cateList"
:key="index"
@click="getChildCategories(index)"
:class="{ active: currentIndex === index }"
>
{{ item.cat_name }}
</text>
</scroll-view>
</view>
<!-- 子级分类 -->
<view class="sub">
<scroll-view scroll-y>
<!-- 封面图 -->
<image
src="http://static.botue.com/ugo/uploads/category.png"
class="thumb"
></image>
<view
class="children"
v-for="(item, index) in childcate"
:key="index"
>
<view class="title">{{ item.cat_name }}</view>
<!-- 品牌 -->
<view class="brands">
<navigator
:url="
'/pages/list/index?query=' + item.cat_name
"
:key="index"
v-for="(item, index) in item.children"
>
<image :src="item.cat_icon"></image>
<text>{{ item.cat_name }}</text>
</navigator>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import search from '@/components/search'
export default {
data() {
return {
// 顶级分类
topCategories: [],
// 当前顶级分类的索引值
currentIndex: 0,
cateList: [],
}
},
// 计算属性
computed: {
childcate() {
return (
this.cateList.length &&
this.cateList[this.currentIndex].children
)
},
},
methods: {
// 获取顶级(一级)分类
async getTopCategories() {
// 请求后端接口
const res = await this.http({
url: '/api/public/v1/categories',
})
// 响应的数据
console.log(res[1].data.message)
this.cateList = res[1].data.message
},
// 点击一级分类获得索引
getChildCategories(index) {
this.currentIndex = index
},
},
// 初次加载获取分类
onLoad() {
this.getTopCategories()
},
}
</script>
<style scoped lang="less">
scroll-view {
height: 100%;
}
.category {
display: flex;
width: 100%;
position: absolute;
top: 100rpx;
bottom: 0;
.sup {
width: 196rpx;
background-color: #f4f4f4;
text {
display: block;
height: 100rpx;
text-align: center;
line-height: 100rpx;
font-size: 27rpx;
color: #333;
border-bottom: 1rpx solid #eee;
&:last-child {
border-bottom: none;
}
&.active {
background-color: #fff;
color: #ea4451;
position: relative;
&::before {
content: '';
display: block;
width: 8rpx;
height: 60rpx;
transform: translateY(-50%);
background-color: #ea4451;
position: absolute;
left: 0;
top: 50%;
}
}
}
}
.sub {
flex: 1;
padding: 20rpx 18rpx;
.thumb {
width: 100%;
height: 180rpx;
}
.children {
text-align: center;
color: #333;
.title {
display: inline-block;
margin: 40rpx 0 20rpx;
font-size: 30rpx;
&::before {
content: '/';
margin-right: 20rpx;
color: #666;
}
&::after {
content: '/';
margin-left: 20rpx;
color: #666;
}
}
}
.brands {
display: flex;
flex-wrap: wrap;
navigator {
width: 33%;
margin-bottom: 20rpx;
}
image {
width: 120rpx;
height: 120rpx;
}
text {
display: block;
font-size: 24rpx;
}
}
}
}
</style>