效果图:
前端代码:
<template>
<view>
<!-- 选项卡头部 -->
<scroll-view class="tab" scroll-x="true" :scroll-left="scrollLeft" >
<block v-for="(item,index) in tabData" :key="index" >
<!-- 标签动态样式 -->
<view class="tab-item" :class=" [currentTab==index ? 'active' : 'none'] " :data-current="index" @click="clickTab">
{{item.title}}
</view>
</block>
</scroll-view>
<!-- 选项卡页面 -->
<swiper class="swiper" :current="currentTab" duration="300" @change="swiperTab" :style=" {height: windowHeight +'px'} ">
<swiper-item v-for="(item,index) in tabData" :key="index">
<scroll-view scroll-y="true" :style=" {height: windowHeight +'px'} " @scrolltolower="getMore" >
<view class="page-item" >
<view v-for="(item,index2) in contentData" :key="index2">
<!-- v-if="currentTab==item.type" 只渲染当前页面对应的数据,不然每个页面的内容都相同-->
<view class="page-item-box" v-if="currentTab==item.type">
<image class="box-image" mode="aspectFill" :src="item.imgeUrl" ></image>
<view> {{item.content}} </view>
</view>
</view>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
</template>
<script>
export default {
data() {
return {
currentTab: 0, //标签初始位置
scrollLeft: 0, //tab标题的滚动条位置
windowHeight: 0,
windowWidth: 0,
tabData:[ //标签数据
{type:0,title:"最新"},
{type:1,title:"热门"},
{type:2,title:"电影"},
{type:3,title:"电视"},
{type:4,title:"综艺"},
{type:5,title:"体育"},
{type:6,title:"教育"},
],
contentData: [] //内容数据
}
},
onLoad() {
wx.getSystemInfo({ //获取系统信息
success: (res) => {
this.windowHeight = res.windowHeight
this.windowWidth = res.windowWidth
}
});
this.getData()
},
methods: {
//点击切换
clickTab(e) {
let clickIndex = e.target.dataset.current //当前标签的索引
let singleNavWidth = this.windowWidth / 5 //每个标签的宽度, 显示5个标签
this.scrollLeft = (clickIndex - 2) * singleNavWidth //水平滚动条位置, tab选项居中
if (this.currentTab === clickIndex) {
return false;
} else {
this.currentTab = clickIndex //使页面对应标签
this.getData()
}
},
//滑动切换
swiperTab(e) {
let swiperIndex = e.detail.current //当前页面的索引
let singleNavWidth = this.windowWidth / 5 //每个标签的宽度 ,显示5个标签
this.scrollLeft = (swiperIndex - 2) * singleNavWidth //使标签跟随页面滚动,超过屏幕范围的标签显示出来
this.currentTab = swiperIndex //使标签对应页面
this.getData()
},
//根据页面索引获取对应的云数据
getData() {
let type = this.currentTab
const db = wx.cloud.database() //引用默认环境的数据库,指定环境: wx.cloud.database({env: 'test'})
db.collection('videoImages') //云端数据库里面的集合名称
.where({type:type})
.get({
success:(res) =>{ //箭头函数能直接使用 this
//console.log('请求成功',res)
this.contentData.push(...res.data)
},
fail:(err) =>{
console.log('获取数据失败',err)
}
})
},
// 加载更多
getMore(){
//this.getData()
}
}
}
</script>
<style>
page{
height: 100%;
width: 100%;
}
.tab{ /* 标签栏 */
height: 80rpx;
width: 100%;
box-sizing: border-box;
overflow: hidden;
line-height: 80rpx;
background: #f7f7f7;
font-size: 16px;
white-space: nowrap;
/* 固定吸顶 */
position: fixed;
top: 0;
left: 0;
z-index: 99;
}
.tab-item{ /* 单个标签 */
width: 20%;
display: inline-block;
text-align: center;
}
.active{ /* 选项卡活动时的样式 */
color:#F65959;
font-size: 20px;
}
.page-item{
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
padding-top: 80rpx;
padding-left: 16rpx;
}
.page-item-box{
display: flex;
flex-direction: column;
height: 320rpx;
width: 220rpx;
/* background-color: #808080; */
/* border:1px solid #cc22b0; */ /* 边框 */
border-radius: 5px;
box-shadow: 0 2px 2px rgba(34, 25, 25, 0.4); /* 框阴影 */
text-align: center; /* 居中对齐 */
margin: 10rpx;
}
.box-image{
height: 280rpx;
width: 220rpx;
border-radius: 5px;
}
</style>
后端数据格式:
以下是2021-11-03更新 【双列分类】
<template>
<view class="page-box">
<!-- 左边栏 -->
<view class="left-tab">
<scroll-view class="tab" scroll-y="true" scroll-with-animation :scroll-top="scrollTop">
<block v-for="(item,index) in tabData" :key="index" >
<!-- 标签动态样式 -->
<view class="tab-item" :class=" [currentTab==index ? 'active' : 'none'] " :data-current="index" @click="clickTab">
{{item.title}}
</view>
</block>
</scroll-view>
</view>
<!-- 右边页面 -->
<block v-for="(item,index) in tabData" :key="index">
<scroll-view class="right-box" scroll-y="true" v-if="currentTab==index">
<view class="page-view">
<view class="class-item">
<view class="item-title">
<text>{{item.title}}</text>
</view>
<view class="item-container">
<view class="thumb-box" v-for="(item1, index1) in contentData" :key="index1">
<image class="item-menu-image" :src="item1.fileID" mode=""></image>
<view class="item-menu-name">标题</view>
</view>
</view>
</view>
</view>
</scroll-view>
</block>
</view>
</template>
<script>
export default {
data() {
return {
windowHeight: 0,
windowWidth: 0,
currentTab: 0, //标签初始位置
hasMore:true ,
pageIndex: 1 ,
contentData: [], //内容数据
tabData:[ //标签数据
{type:0,title:"爱情"},
{type:1,title:"唯美"},
{type:2,title:"动漫"},
{type:3,title:"风景"},
{type:4,title:"可爱"},
{type:5,title:"创意"},
{type:6,title:"鲜花"},
{type:7,title:"汽车"},
{type:8,title:"运动"},
{type:9,title:"游戏"},
{type:10,title:"新闻"},
{type:11,title:"军事"},
{type:12,title:"经济"}
]
}
},
onLoad() {
uni.getSystemInfo({ //获取系统信息
success: (res) => {
this.windowHeight = res.windowHeight
this.windowWidth = res.windowWidth
}
});
this.getData()
},
// 分享给朋友
onShareAppMessage: function () { },
//分享到朋友圈
onShareTimeline: function () { },
methods: {
//点击左边切换
clickTab(e) {
let clickIndex = e.target.dataset.current //当前标签的索引
this.currentTab = clickIndex //使页面对应标签
this.pageIndex = 1
this.hasMore = true
this.contentData = []
this.getData()
},
//根据页面索引获取对应的云数据
getData() {
if(this.hasMore) {
uni.showLoading({
title: '加载中...'
})
let type = parseInt(this.currentTab) //字符串转数字
let pageIndex = parseInt(this.pageIndex)
uniCloud.callFunction({ //调用云函数
name:'getUrl', //云函数名称
data:{ //以下是云函数需要传入的参数
filter:{type:type}, //筛选条件
pageIndex: pageIndex , //第几页
pageSize: 30 //每页的记录条数
},
success:(res) => {
console.log(res)
this.contentData.push(...res.result.data) //云端返回的查询数据,追加到数组
this.hasMore = res.result.hasMore //云端返回的是否有更多数据
if (this.hasMore) {
this.pageIndex = this.pageIndex + 1
}
},
fail:()=> {
console.log('调用云函数失败')
},
complete:() => {
uni.hideLoading()
}
})
} else {
uni.showToast({
title:'没有更多数据了',
icon:'none'
})
}
}
}
}
</script>
<style>
.page-box{
display: flex;
flex-direction: row;
height: calc(100vh); /* 需要定义高度,否则不能分栏滚动 */
/* #ifdef H5 */
height: calc(100vh - var(--window-top));
/* #endif */
}
.left-tab{
flex: 1; /*均匀分配元素*/
display: flex;
overflow: hidden;
}
.tab{
width: 150rpx;
height: 100%;
}
.tab-item{
height: 110rpx;
background: #f6f6f6;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
color: #444;
font-weight: 400;
line-height: 1;
}
.active{ /* 选项卡活动时的样式 */
color:#F65959;
font-size: 20px;
background: #ffffff;
}
/* 右边页面样式 */
.right-box {
left: 15%;
width: 80%;
background: #f6f6f6;
}
.page-view {
padding: 10rpx;
}
.class-item {
margin-bottom: 30rpx;
background-color: #fff;
padding: 16rpx;
border-radius: 8rpx;
}
.item-title {
font-size: 26rpx;
color: $u-main-color;
font-weight: bold;
}
.item-menu-name {
font-weight: normal;
font-size: 24rpx;
color: $u-main-color;
}
.item-container {
display: flex;
flex-wrap: wrap;
}
.thumb-box {
width: 33.333333%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
margin-top: 20rpx;
}
.item-menu-image {
width: 120rpx;
height: 120rpx;
}
</style>
云开发的壁纸分享小程序