在本篇文章中,基于《黑马商城》项目,
分析双侧(或多侧)滑动列表的实现,使用场景常常是类别与详情之间的对应
效果如下:
如上图所示,左侧点击“家居生活”,右侧显示与家居生活相关的内容;左侧点击点击“摄影设计”,右侧显示与摄影设计相关的内容;左侧点击“明星美女”,右侧显示与明星美女相关的内容,
并且在左侧点击相应区域时,相应区域会变红。
在右侧,点击图片,有放大效果显示。并且可以滑动切换所有的图片
对于页面的框架,HTML部分,代码如下:
<template>
<view class="pics">
<scroll-view class="left" scroll-y>
<view
@click="leftClickHandle(index,item.id)"
:class="active===index?'active':''"
v-for="(item,index) in cates"
:key="item.id">
{{item.title}}
</view>
</scroll-view>
<scroll-view class="right" scroll-y>
<view class="item" v-for="item in secondData" :key="item.id">
<image @click="previewImg(item.img_url)" :src="item.img_url"></image>
<text>{{item.title}}</text>
</view>
<text v-if="secondData.length === 0">暂无数据</text>
</scroll-view>
</view>
</template>
双侧都使用了uniapp的scroll-view组件
使用页面生命周期函数onLoad,在页面加载的时候,调用getPicsCate()方法
onLoad () {
this.getPicsCate()
}
getPicsCate()方法代码如下:
async getPicsCate () {
const res = await this.$myRuquest({
url: '/api/getimgcategory'
})
this.cates = res.data.message
this.leftClickHandle(0,this.cates[0].id)
},
发起请求,获取左侧列表图片分类数据:
并保存在cates列表中,
并在这个方法中,调用leftClickHandle()方法,传入参数0,和第0项的id,表示默认显示第一个图片类别的内容。
对于leftClickHandle()方法,代码如下:
async leftClickHandle (index,id) {
this.active = index
// 获取右侧的数据
const res = await this.$myRuquest({
url: '/api/getimages/'+id
})
this.secondData = res.data.message
},
传入参数的index(0,1,2,...)代表active的值,表示哪一个分类项将会被变红高亮,然后发起请求根据参数该项的id获取右侧图片列表的数据
并把获取到的数据保存到secondData列表中。
对于页面的框架HTML部分
<template>
<view class="pics">
<scroll-view class="left" scroll-y>
<view
@click="leftClickHandle(index,item.id)"
:class="active===index?'active':''"
v-for="(item,index) in cates"
:key="item.id">
{{item.title}}
</view>
</scroll-view>
<scroll-view class="right" scroll-y>
<view class="item" v-for="item in secondData" :key="item.id">
<image @click="previewImg(item.img_url)" :src="item.img_url"></image>
<text>{{item.title}}</text>
</view>
<text v-if="secondData.length === 0">暂无数据</text>
</scroll-view>
</view>
</template>
左侧列表
使用v-for指令对view视图容器进行循环,动态绑定的key是该项的id,显示出该项的title
对于每一项来言,动态绑定class,如果当前active的值和index相等,则class=active,否则为空,对于active的赋值是在leftClickHandle()方法
这个方法在两个情况下调用:
(1)一个是在页面加载时调用(相当于初始化)
(2)另一个是在左侧列表每一项的点击事件,赋值active
对于左侧列表的每一项来言,检查active是否与自己的index值相同,若相同则class=active,否则为空串。
在css中,class active代码如下:
.active{
background: $shop-color;
color: #fff;
}
背景为红色,字体颜色为白色
右侧列表
<scroll-view class="right" scroll-y>
<view class="item" v-for="item in secondData" :key="item.id">
<image @click="previewImg(item.img_url)" :src="item.img_url"></image>
<text>{{item.title}}</text>
</view>
<text v-if="secondData.length === 0">暂无数据</text>
</scroll-view>
使用v-for指令循环secondData列表,动态绑定key为每一项的id
对于每一项,共有两项分别是图片和文字
对于文字部分,显示每一项的title
对于图片部分,动态绑定每一项的img_url,
对于每一张图片的点击事件是previewImg(item.img_url)方法
代码如下:
previewImg (current) {
const urls = this.secondData.map(item=>{
return item.img_url
})
uni.previewImage({
current,
urls
})
}
在该方法中,调用uniapp提供的图片接口previewImage(),该接口用来预览图片
current是指当前预览的图片的url,urls是指可以滑动的所有图片url列表
注意:如果对象内。键和值相等,可以只写键
对于text标签,使用v-if指令,如果secondData列表为空的话(v-if='true'),则显示暂无数据
下面我们来分析该页面的样式。
代码如下:
<style lang="scss">
page{
height: 100%;
}
.pics{
height: 100%;
display: flex;
.left{
width: 200rpx;
height: 100%;
border-right:1px solid #eee;
view{
height: 60px;
line-height: 60px;
color: #333;
text-align: center;
font-size: 30rpx;
border-top:1px solid #eee;
}
.active{
background: $shop-color;
color: #fff;
}
}
.right{
height: 100%;
width: 520rpx;
margin: 10rpx auto;
.item{
image{
width: 520rpx;
height: 520rpx;
border-radius: 5px;
}
text{
font-size: 30rpx;
line-height: 60rpx;
}
}
}
}
</style>
总体页面的高度为100%,占满全屏
总的class是pics,采用flex布局(则默认是在一行中显示)
分为left,right类
对于左侧,限制宽度为200rpx,高度设为100%,右侧设置1像素的实线,颜色为浅灰色
对于左侧的每一项,高度为60px,行高(文本内容的高度)为60px,字体颜色为灰色,文字居中,字体大小为30rpx,每一项的上侧设置1像素,且为灰白色的实线
对于右侧 ,限制宽度为520rpx,高度设置为100%,margin设置为上下为10rpx,左右设置为auto(居中)
对于右侧的每一项,对于图片,设置宽度为50rpx,高度为520rpx,5px的边框圆角;对于文字,字体大小为30rpx,行高为60rpx