1.顶栏滑块和swiper 案例:
<template>
<view class="content">
<!-- 顶栏
触摸变颜色
changeTab(index)
~~~~~~~~~~~~~~~~~~~~~~~~
滑动scroll-view让顶栏跟着动
:scroll-into-view='scrollIntoIndex'
scrollIntoIndex为子元素的id值不能为0
:id="'top'+index"
-->
<scroll-view scroll-x="true" class='scroll-content' :scroll-into-view='scrollIntoIndex'>
<view
:id="'top'+index"
class='scroll-item'
v-for='(item,index) in topBar'
:key='index'
@tap='changeTab(index)'
>
<text
:class='topBarIndex===index?
"f-active-color":"f-color"'
>{{item.name}}</text>
</view>
</scroll-view>
<!-- 滑动栏
点击scroll-view 切换 swiper-item内容
@change='onChangeTab' :current="topBarIndex"
当current改变,触发change事件
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
<swiper @change='onChangeTab' :current="topBarIndex">
<swiper-item
v-for='(item,index) in topBar'
:key='index'
>
<view>{{item.name}}</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
export default {
data() {
return {
//选中的索引
topBarIndex:0,
//顶栏跟随的索引id值
scrollIntoIndex:'top0',
//顶栏数据
topBar:[
{name:'推荐'},
{name:'运动户外'},
{name:'服饰内衣'},
{name:'鞋靴箱包'},
{name:'美妆个护'},
{name:'家居数码'},
{name:'食品母婴'}
]
}
},
methods:{
changeTab(index){
if(this.topBarIndex === index){
return ;
}
// 触摸,变颜色
this.topBarIndex = index;
// 滑动scroll-view让顶栏跟着动
this.scrollIntoIndex = 'top'+index;
},
onChangeTab(e){
// 点击scroll-view 切换 swiper-item内容
this.changeTab(e.detail.current);
}
}
}
</script>
<style lang="scss" scoped>
.scroll-content{
width: 100%; //一定要
height: 80rpx;
white-space: nowrap; //一定要,不换行,[不加没有后面内容]
.scroll-item{
display: inline-block; //一定要
padding:10rpx 30rpx;
font-size:32rpx;
.f-active-color{
color:#1296db;
padding:10rpx 0;
border-bottom:6rpx solid #49BDFB;
}
}
}
</style>
2.进阶版-顶栏滑块和swiper的案例
<template>
<view class="content">
<!-- 顶栏
触摸变颜色
changeTab(index)
~~~~~~~~~~~~~~~~~~~~~~~~
滑动scroll-view让顶栏跟着动
:scroll-into-view='scrollIntoIndex'
scrollIntoIndex为子元素的id值不能为0
:id="'top'+index"
-->
<scroll-view scroll-x="true" class='scroll-content'
:scroll-into-view='scrollIntoIndex'>
<view
:id="'top'+index"
class='scroll-item'
v-for='(item,index) in topBar'
:key='index'
@tap='changeTab(index)'
>
<text :class='topBarIndex===index? "f-active-color":"f-color"'
>
{{item.name}}</text>
</view>
</scroll-view>
<!-- 滑动栏
点击scroll-view 切换 swiper-item内容
@change='onChangeTab' :current="topBarIndex"
当current改变,触发change事件
-->
<swiper @change='onChangeTab'
:current="topBarIndex"
style="background-color: #007AFF;"
:style="'height:' + clientHeight + 'px;'">
<swiper-item
v-for='(item,index) in newTopBar'
:key='index'
>
<!-- <view class='indexData'> 不用了,因为获取不到这个内容了-->
<!-- 采用这个scroll-view,是为了可以触底加载,不是为了滑动 -->
<scroll-view scroll-y="true"
:style="'height:' + clientHeight + 'px;'"
>
<view>这里面放数据</view>
</scroll-view>
<!-- </view> -->
</swiper-item>
</swiper>
</view>
</template>
<script>
export default {
data() {
return {
//选中的索引
topBarIndex:0,
//顶栏跟随的索引id值
scrollIntoIndex:'top0',
//顶栏数据
topBar:[
{name:'推荐'},
{name:'运动户外'},
{name:'服饰内衣'},
{name:'鞋靴箱包'},
{name:'美妆个护'},
{name:'家居数码'},
{name:'食品母婴'}
],
// 内容块的高度值
clientHeight:0,
// 承载数据
newTopBar:[]
}
},
onReady() {
// 获取可视区域的高度
uni.getSystemInfo({
success: (res) => {
console.log(res);
// ios是--有问题的,下面就兼容
this.clientHeight = res.windowHeight - uni.upx2px(80)-this.getClientHeight();
}
})
},
methods:{
changeTab(index){
if(this.topBarIndex === index){
return ;
}
// 触摸,变颜色
this.topBarIndex = index;
// 滑动scroll-view让顶栏跟着动
this.scrollIntoIndex = 'top'+index;
},
onChangeTab(e){
// 点击scroll-view 切换 swiper-item内容
this.changeTab(e.detail.current);
},
//获取可视区域高度【兼容】
getClientHeight(){
const res = uni.getSystemInfoSync();
const system = res.platform;
if( system ==='ios' ){
return 44+res.statusBarHeight;
}else if( system==='android' ){
// 如果安卓出现bug,就把这个变为0,或者去掉
return 0;
// return 48+res.statusBarHeight;
}else{
return 0;
}
}
}
}
</script>
<style lang="scss" scoped>
.scroll-content{
width: 100%; //一定要
height: 80rpx;
white-space: nowrap; //一定要,不换行,[不加没有后面内容]
.scroll-item{
display: inline-block; //一定要
padding:10rpx 30rpx;
font-size:32rpx;
.f-active-color{
color:#1296db;
padding:10rpx 0;
border-bottom:6rpx solid #49BDFB;
}
}
}
</style>
3.最终版-原装不动的版本+下拉加载[有数据的]
<template>
<view class="content">
<!-- 推荐的有IndexSwiper,Recommend[蓝底板块],Card[-文字-],LikeList[猜你喜欢]-->
<!-- <IndexSwiper></IndexSwiper>
<Recommend></Recommend>
<Card cardTitle='猜你喜欢'></Card>
<LikeList></LikeList> -->
<!-- 运动户外即其他板块 的有 Bannar , Icons , Hot[热销爆品] , Shop[推荐店铺] , LikeList[为您推荐{跟猜你喜欢一样}] -->
<!-- <Banner></Banner>
<Icons></Icons>
<Card cardTitle='热销爆品'></Card>
<Hot></Hot>
<Card cardTitle='推荐店铺'></Card>
<Shop></Shop>
<Card cardTitle='为您推荐'></Card>
<LikeList></LikeList> -->
<!-- 顶栏
触摸变颜色
changeTab(index)
~~~~~~~~~~~~~~~~~~~~~~~~
滑动scroll-view让顶栏跟着动
:scroll-into-view='scrollIntoIndex'
scrollIntoIndex为子元素的id值不能为0
:id="'top'+index"
-->
<scroll-view scroll-x="true" class='scroll-content' :scroll-into-view='scrollIntoIndex'>
<view
:id="'top'+index"
class='scroll-item'
v-for='(item,index) in topBar'
:key='index'
@tap='changeTab(index)'
>
<text :class='topBarIndex===index? "f-active-color":"f-color"'>{{item.name}}</text>
</view>
</scroll-view>
<!-- 滑动栏
点击scroll-view 切换 swiper-item内容
@change='onChangeTab' :current="topBarIndex"
当current改变,触发change事件
-->
<swiper @change='onChangeTab'
:current="topBarIndex"
:style="'height:' + clientHeight + 'px;'">
<swiper-item
v-for='(item,index) in newTopBar'
:key='index'
>
<!-- <view class='indexData'> 不用了,因为获取不到这个内容了-->
<!-- 采用这个,是为了可以触底加载,不是为了滑动 -->
<scroll-view
scroll-y="true"
:style="'height:' + clientHeight + 'px;'"
@scrolltolower='loadMore(index)'
>
<block v-if='item.data.length>0'>
<block v-for='(k,i) in item.data' :key='i'>
<IndexSwiper v-if='k.type==="swiperList"' :dataList='k.data'></IndexSwiper>
<template v-if='k.type==="recommendList"' >
<Recommend :dataList='k.data'></Recommend>
<Card cardTitle='猜你喜欢'></Card>
</template>
<Banner v-if='k.type==="bannerList"' :dataList='k.imgUrl'></Banner>
<template v-if='k.type==="iconsList"' >
<Icons :dataList='k.data'></Icons>
<Card cardTitle='热销爆品'></Card>
</template>
<template v-if='k.type==="hotList"' >
<Hot :dataList='k.data'></Hot>
<Card cardTitle='推荐店铺'></Card>
</template>
<template v-if='k.type==="shopList"' >
<Shop :dataList='k.data'></Shop>
<Card cardTitle='为您推荐'></Card>
</template>
<LikeList v-if='k.type==="likeList"' :dataList='k.data'></LikeList>
</block>
</block>
<block v-else>
暂无数据...
</block>
<!-- 上拉加载的 -->
<view class='load-text f-color'>
{{item.loadText}}
</view>
</scroll-view>
<!-- </view> -->
</swiper-item>
</swiper>
</view>
</template>
<script>
import IndexSwiper from '@/components/index/IndexSwiper.vue'
import Recommend from '@/components/index/Recommend.vue'
import Card from '@/components/common/Card.vue'
import LikeList from '@/components/common/LikeList.vue'
import Banner from '@/components/index/Banner.vue'
import Icons from '@/components/index/Icons.vue'
import Hot from '@/components/index/Hot.vue'
import Shop from '@/components/index/Shop.vue'
export default {
components:{
IndexSwiper,
Recommend,
Card,
LikeList,
Banner,
Icons,
Hot,
Shop
},
data() {
return {
//选中的索引
topBarIndex:0,
//顶栏跟随的索引id值
scrollIntoIndex:'top0',
//顶栏数据
topBar:[
// {name:'推荐'},
// {name:'运动户外'},
// {name:'服饰内衣'},
// {name:'鞋靴箱包'},
// {name:'美妆个护'},
// {name:'家居数码'},
// {name:'食品母婴'}
],
// 内容块的高度值
clientHeight:0,
// 承载数据
newTopBar:[]
}
},
onReady() {
/* 获取节点的信息
如果这个元素内的是组件或者是渲染的话,是获取不到这个节点的!!这是一个坑
所以这个就不用了
*/
// const query = uni.createSelectorQuery().in(this);
// query.select('.indexData').boundingClientRect(data => {
// // console.log(data); //得到这个节点的信息
// this.clientHeight = 3000
// }).exec();
// 获取可视区域的高度
uni.getSystemInfo({
success: (res) => {
// console.log(res);
// ios是--有问题的,下面就兼容
this.clientHeight = res.windowHeight - uni.upx2px(80)-this.getClientHeight();
}
})
},
onLoad() {
this.__init()
},
methods:{
changeTab(index){
if(this.topBarIndex === index){
return ;
}
// 触摸,变颜色
this.topBarIndex = index;
// 滑动scroll-view让顶栏跟着动
this.scrollIntoIndex = 'top'+index;
//每一次滑动请求不同的数据==》赋值first
if( this.newTopBar[this.topBarIndex].load ==='first'){
this.addData();
}
},
onChangeTab(e){
// 点击scroll-view 切换 swiper-item内容
this.changeTab(e.detail.current);
},
__init(){
uni.request({
url:'http://192.168.0.5:3000/api/index_list/data',
success: (res) => {
let data = res.data.data;
// console.log(data)
// topBar数据
this.topBar = data.topBar;
// 首页数据的
this.newTopBar = this.initData(data);
// console.log(this.newTopBar)
}
})
},
// 转变请求过来的数据(这里是根据顶栏多少个,就多少个数组)
initData(res){
let arr = [];
for(let i =0;i<this.topBar.length;i++){
let obj = {
data:[],
load:"first", //这个是为了数据不重复加载
loadText:"上拉加载更多..."
}
//获取首次数据
if(i==0){
obj.data = res.data;
}
arr.push(obj)
}
return arr;
},
//获取可视区域高度【兼容】
getClientHeight(){
const res = uni.getSystemInfoSync();
const system = res.platform;
if( system ==='ios' ){
return 44+res.statusBarHeight;
}else if( system==='android' ){
// return 48+res.statusBarHeight;
return 0;
}else{
return 0;
}
},
//滑动不同板块--请求不同数据
addData(callback){
//拿到索引
let index = this.topBarIndex;
//拿到id
let id = this.topBar[index].id;
//请求不同的板块的数据下拉刷新的
let page = Math.ceil(this.newTopBar[index].data.length / 5) + 1;
//请求不同的数据
uni.request({
url:`http://192.168.0.5:3000/api/index_list/${id}/data/${page}`,
success: (res) => {
// 这个是为了滑动到没有接口的,抑制不会报错
if(res.statusCode != 200){
return;
}else{
let data = res.data.data;
this.newTopBar[index].data = [...this.newTopBar[index].data,...data];
}
}
})
/*当请求结束后,重新赋值, 为了数据不重复加载
this.newTopBar[index].data = [...this.newTopBar[index].data,...data];
因为这个,每次滑动,都会重复加载数据的
*/
this.newTopBar[index].load='last';
//上拉加载的
if(typeof callback==='function'){
callback();
}
},
//上拉加载更多
loadMore(index){
this.newTopBar[index].loadText = '加载中...';
//请求完数据 ,文字提示信息又换成【上拉加载更多...】
this.addData(()=>{
this.newTopBar[index].loadText = '上拉加载更多...';
})
}
}
}
</script>
<style lang="scss" scoped>
.scroll-content{
width: 100%; //一定要
height: 80rpx;
white-space: nowrap; //一定要,不换行,[不加没有后面内容]
.scroll-item{
display: inline-block; //一定要
padding:10rpx 30rpx;
font-size:32rpx;
.f-active-color{
color:#1296db;
padding:10rpx 0;
border-bottom:6rpx solid #49BDFB;
}
}
}
</style>
最终版后端的数据:
//后端:首次推荐--第一次触底的数据
router.get('/api/index_list/1/data/2', function(req, res, next) {
res.json({
code:"0",
data:[
{
type: "likeList",
data: [{
id: 1,
imgUrl: "../../static/images/commodity/commodity1.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
}
]
}
]
})
})
// 后端:首页数据--推荐
router.get("/api/index_list/data", function(req, res, next) {
res.send({
"code": 0,
"data": {
topBar: [{
id: 1,
name: '推荐'
},
{
id: 2,
name: '运动户外'
}
],
data: [{
type: "swiperList",
data: [{
imgUrl: '../../static/images/swiper/swiper1.jpg'
}
]
},
{
type: "recommendList",
data: [{
bigUrl: "../../static/images/children/Children.jpg",
data: [{
imgUrl: "../../static/images/children/Children1.jpg"
},
]
},
{
bigUrl: "../../static/images/Furnishing/Furnishing.jpg",
data: [{
imgUrl: "../../static/images/Furnishing/Furnishing1.jpg"
}
]
}
]
},
{
type: "likeList",
data: [{
id: 1,
imgUrl: "../../static/images/commodity/commodity1.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
}
]
}
]
}
})
});
// 后端:首页数据--运动户外
router.get('/api/index_list/2/data/1', function(req, res, next) {
res.json({
code: "0",
data: [{
type: "bannerList",
imgUrl: "../../static/images/banner1.jpg"
},
{
type: "iconsList",
data: [{
imgUrl: "../../static/images/icon/icons1.png",
name: "运动户外"
},
{
imgUrl: "../../static/images/icon/icons2.png",
name: "运动户外"
},
{
imgUrl: "../../static/images/icon/icons3.png",
name: "运动户外"
},
{
imgUrl: "../../static/images/icon/icons8.png",
name: "运动户外"
}
]
},
{
type: "hotList",
data: [{
id: 1,
imgUrl: "../../static/images/hot/hot1.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
},
{
id: 2,
imgUrl: "../../static/images/hot/hot2.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
}
]
},
{
type: "shopList",
data: [{
bigUrl: "../../static/images/shop/shop.jpg",
data: [{
id: 1,
imgUrl: "../../static/images/shop/shop1.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
},
{
id: 2,
imgUrl: "../../static/images/shop/shop2.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
},
{
id: 3,
imgUrl: "../../static/images/shop/shop3.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
},
{
id: 4,
imgUrl: "../../static/images/shop/shop4.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
}
]
}
]
},
{
type: "likeList",
data: [{
id: 1,
imgUrl: "../../static/images/commodity/commodity1.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
},
{
id: 2,
imgUrl: "../../static/images/commodity/commodity2.jpg",
name: "大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008大姨绒毛大款2020年必须买,不买你就不行了,爆款疯狂GG008",
pprice: "299",
oprice: "659",
discount: "5.2"
}
]
}
]
})
});``