微信小程序分类-左侧导航与右侧内容联动

左侧导航与右侧内容联动
一、首先是点击左侧导航,我们右侧内容需要滑动至相应的位置。

思路是:点击左侧某一项,获取该元素的id,也就是左侧view的id,然后动态传到右侧内容的scroll-into-view,scroll-into-view的值为某个子元素的id,
这里的子元素说的是右侧的view,我们将左侧view的id和右侧view的id设置为同一个值时,这样当左侧id发生变化时,scroll-into-view会帮助我们将右侧view进行相应的变化。
如图:

 

 

数据不同,data-id='a{{item.id}}'替换成你数据的参数id(左侧栏数据的id)
二、接下来是右侧滚动,左侧对应选中,也就是高亮。

思路是:既然是滚动,我们需要用到scroll-view中的bindscroll属性(绑定滚动事件,和bindtap点击事件类似,点击触发bindtap监听,滚动触发bindscroll监听),
每次右侧滚动时,我们需要计算当前滚动的高度,当滚动超过左侧分类商品在右侧中占据的高度时,我们将动态修改左侧导航的id。
实际上当数据都显示的时候,我们计算每一项分类在右侧占据的高度,当滚动超过这个高度时,我们就修改左侧导航的id,这样我们就实现了高亮。
如图:

需要注意的是以上的红色圈部分,两个图中的红色圈id要一样
计算右侧占据高度的方法是通过wx.createSelectorQuery()。
我的数据是{{good}}这个,每个人的数据不一样,但方法是相通的,按照我的文字和图进行操作是一定可以实现的。

三、最后一点问题  

我们在判断滚动的高度是否超出时,最好给最初的scrollTop加上10,因为如果为0,当我点击第二个分类时,滑动可能还没有超出第一个分类占据的高度,那么高亮就会发生计算错误;还有就时如果分类中后面的商品过少,滑动时高亮也没有发生变化,所以最好时在最后的一个分类上做一些处理,比如加上占据高度,如图。


源码部分
js:

data: {

winHeight: 0,

good: [],

contentActive: '', // 内容栏id

navActive: 0, // 导航栏选中id

heightArr: [],

containerH: 0,

},

onLoad: function () {

// 获取窗口可用高度

wx.getSystemInfo({

success: res => {

this.setData({

winHeight: res.windowHeight

});

}

});

// 在请求网络数据之后里面---------

this.setData({

good: res

})

this.setHeightArr();

});

// 在请求网络数据之后里面写以上-------

},

 

setHeightArr:function(){

let query = wx.createSelectorQuery().in(this);

let heightArr = [];

let s = 0;

query.selectAll('.vertical-list').boundingClientRect((react) => {

react.forEach((res) => {

s += res.height;

heightArr.push(s)

});

this.setData({

heightArr: heightArr

})

});

query.select('.content').boundingClientRect((res) => {

// 计算容器高度

this.setData({

containerH: res.height

})

}).exec();

},

 

onScroll(e) {

let scrollTop = e.detail.scrollTop;

scrollTop += 10;

let scrollArr = this.data.heightArr;

if (scrollTop >= scrollArr[scrollArr.length - 1] - this.data.containerH) {

return

} else {

for (let i = 0; i < scrollArr.length; i++) {

if (scrollTop >= 0 && scrollTop < scrollArr[0]) {

console.log('==============aaa' + scrollTop + "==" + scrollArr[0]);

this.setData({

navActive: 0

})

} else if (scrollTop >= scrollArr[i - 1] && scrollTop < scrollArr[i]) {

console.log('==============bbb' + scrollTop + "==" + scrollArr[i]);

this.setData({

navActive: i

})

}

}

}

},

 

chooseType: function(e) {

let id = e.currentTarget.dataset.id;

let index = e.currentTarget.dataset.index;

console.log('=============id' + id + "--" + index);

this.setData({

toView: id,

navActive: index

})

},

 

wxml:
<view class="book-box">

<view class="swiper-vertical-tab">

<scroll-view class='swipter-nav' scroll-y="true" style="height:{{winHeight}}px;">

<view wx:for="{{good}}" wx:key="item" class="{{index===navActive ? 'active' : ''}}" bindtap="chooseType" data-id='a{{item.id}}' data-index='{{index}}'>

{{item.foodType}}

</view> 

</scroll-view>

</view>

 

<view class="content content-class">

<scroll-view class="swiper-vertical-box" scroll-y="true" style="height:{{winHeight}}px;" scroll-into-view="{{toView}}" scroll-with-animation="true" bindscroll="onScroll">

<view class="vertical-list" id="a{{item.id}}" wx:for="{{good}}" wx:key="foodType" wx:for-index="idx"> 

<text class="title">{{item.foodType}}</text>

<block wx:if="{{item.data.length}}">

<view class="type-detail">

<view wx:for="{{item.data}}" wx:key="foodDetail" wx:for-index="jdx">

<navigator url="/pages/good/index?id={{item.objectId}}">

<image src="{{item.menu_logo}}" mode="aspectFill"></image>

<view class="book-detail">

<text>{{item.menu_name}}</text>

<view>

<text class="money">¥{{item.price}}</text>

<view class="operations smallsize">

销量:{{item.sale_number}}

</view>

</view>

</view>

</navigator>

</view>

</view>

</block>

<block wx:else>

<view class='noshop'>暂无商品</view>

</block>

</view>

</scroll-view>

</view>

</view> 

wxss:
page {

background: #f0f0f0;

font-family: "微软雅黑",

Helvetica,

Arial,

"Hiragino Sans GB",

"Source Han Sans CN",

"PingFang SC",

Roboto,

"Heiti SC",

"Microsoft Yahei",

sans-serif;

background: #fff;

width: 100%;

height: 100%;

}

 

.book-box .content {

flex: 1;

background: #fff;

height: 100%;

}

 

.swiper-tab {

margin-top: 10px;

height: 20px;

padding: 10px 0;

background: #fff;

display: flex;

font-size: 17px;

line-height: 20px;

border-bottom: 1px solid #e6e6e6;

}

 

.swiper-tab-list {

flex: 1;

text-align: center;

position: relative;

color: #787878;

}

 

.swiper-tab-list:first-of-type {

border-right: 1px solid #c8c8c8;

}

 

.swiper-tab-list.on {

color: #fa4b22;

}

 

.swiper-tab-list.on::after {

content: "";

height: 2px;

width: 100px;

background: #fa4b22;

position: absolute;

left: 50%;

margin-left: -50px;

bottom: -10px;

}

 

.book-box {

width: 100%;

height: 100%;

position: absolute;

top: 0;

left: 0;

bottom: 0;

display: flex;

overflow: scroll;

}

 

.book-box, .order-box {

width: 100%;

position: relative;

box-sizing: border-box;

}

 

.swiper-vertical-box {

box-sizing: border-box;

flex: 1;

}

 

.order-box {

background: #fff;

}

 

.swiper-vertical-tab {

width: 200rpx;

left: 0px;

top: 0;

height: 100%;

}

 

.swiper-vertical-tab view {

height: 50px;

font-size: 15px;

color: #505050;

text-align: center;

box-sizing: border-box;

padding-top: 12px;

}

 

.swiper-vertical-tab {

background: #eee;

}

 

.swiper-vertical-tab view.active {

background: #fff;

}

 

.swiper-vertical-box .vertical-list {

/* height: 300px; */

}

 

.swiper-vertical-box .vertical-list .title {

height: 40px;

padding-left: 20px;

background: #f5f5f5;

color: #646464;

line-height: 40px;

font-size: 15px;

display: block;

}

 

.type-detail {

background: #fff;

}

 

.type-detail>view {

border-bottom: 1px solid #e5e5e5;

margin-left: 10px;

overflow: hidden;

padding-left: 80px;

box-sizing: border-box;

position: relative;

height: 92px;

width: 100%;

margin-bottom: -1px;

}

 

.type-detail view image {

width: 70px;

height: 70px;

border-radius: 6px;

margin-top: 10px;

/* border: 1px solid #ccc; */

float: left;

margin-bottom: 10px;

position: absolute;

left: 0;

top: 0;

}

 

.book-detail {

padding-right: 20px;

}

 

.book-detail>text {

font-size: 15px;

color: #505050;

margin-top: 10px;

display: block;

text-overflow: ellipsis;

display: -webkit-box;

-webkit-box-orient: vertical;

-webkit-line-clamp: 2;

overflow: hidden;

font-weight: bold;

}

 

.book-detail button, .book-result-detail button {

float: left;

width: 27px;

height: 28px;

border-radius: 14px;

}

 

.book-detail>view text {

float: left;

}

 

.book-detail>view view {

float: left;

}

 

.book-detail>view {

width: 100%;

overflow: hidden;

position: relative;

height: 28px;

display: flex;

align-items: center;

justify-content: space-between;

}

 

.book-detail button.reduce, .book-result-detail button.reduce {

background: url(http://bmob-cdn-8770.b0.upaiyun.com/2017/03/01/3b2b07294075d7b78025de3a115733c1.png) no-repeat;

background-size: 100% auto;

}

 

.book-detail button.add, .book-result-detail button.add {

background: url(http://bmob-cdn-8770.b0.upaiyun.com/2017/03/01/23438bf040336dd980b7bfdd294d0265.png) no-repeat;

background-size: 100% auto;

}

 

.book-detail .money {

font-size: 15px;

color: #fa4b22;

line-height: 27px;

}

 

.operations text {

line-height: 27px;

color: #333;

width: 35px;

display: block;

text-align: center;

}

 

.Bill-layer {

width: 100%;

height: 100%;

background: #000;

opacity: 0.5;

position: fixed;

left: 0;

top: 0;

z-index: 1;

}

 

.Bill {

position: fixed;

left: 0;

bottom: 0;

width: 100%;

z-index: 2;

}

 

.takeBill {

height: 50px;

background: #fff;

position: relative;

}

 

.takeBill .box-right {

width: 120px;

height: 52px;

background: #fa4d22;

position: absolute;

right: 0;

top: -1px;

border-radius: 0;

color: #fff;

line-height: 52px;

text-align: center;

}

 

.box-left {

margin-left: 30px;

}

 

.box-left>view {

float: left;

}

 

.box-left .tips {

width: 30px;

position: relative;

background: url(http://bmob-cdn-8770.b0.upaiyun.com/2017/03/01/d2c8205d404de1228042eff53f758aed.png) no-repeat left 12px;

background-size: 100% auto;

height: 40px;

position: relative;

}

 

.box-left .tips view {

position: absolute;

right: -5px;

top: 7px;

width: 20px;

height: 20px;

background: #f55022;

color: #fff;

border-radius: 10px;

text-align: center;

line-height: 20px;

font-size: 12px;

}

 

.box-left .moeny {

color: #fa4b22;

font-size: 17px;

margin-left: 10px;

margin-top: 15px;

}

 

.clearCart {

height: 35px;

text-align: right;

background: #f5f5f5;

}

 

.clearCart button {

background: none;

float: right;

color: #646464;

line-height: 35px;

font-size: 14px;

padding-left: 16px;

background: url(http://bmob-cdn-8770.b0.upaiyun.com/2017/03/01/b89dba9340a615f8805f9fa477898dfd.png) no-repeat left center;

background-size: 13px auto;

}

 

.clearCart button::after {

border: 0 none;

}

 

.book-result-detail {

overflow: hidden;

}

 

.book-result-detail>view {

background: #fff;

overflow: hidden;

height: 50px;

padding-top: 10px;

padding-left: 15px;

box-sizing: border-box;

padding-right: 10px;

border-bottom: 1px solid #e6e6e6;

}

 

.book-result-detail>view text {

float: left;

}

 

.book-result-detail>view view {

float: right;

}

 

.food-detail {

overflow: hidden;

height: 36px;

line-height: 36px;

}

 

.food-detail>text {

float: left;

color: #3c3c3c;

font-size: 18px;

display: block;

}

 

.food-detail>view {

float: right;

}

 

.food-detail>view text {

font-size: 15px;

color: #999;

}

 

.place {

height: 5px;

width: 100%;

background: #f0f0f0;

}

 

.order-list {

border-top: 1px solid #e6e6e6;

border-bottom: 1px solid #e6e6e6;

margin-top: -1px;

padding: 20px 15px;

}

 

.order-list>text {

color: #3c3c3c;

font-size: 17px;

margin-bottom: 6px;

display: block;

}

 

.order-list .time {

color: #999;

font-size: 13px;

text-align: right;

}

 

.bdt {

border-top: 1px solid #e6e6e6;

}

 

.hidden {

display: none;

}

 

.show {

display: block;

}

 

.noshop {

text-align: center;

margin: 40rpx;

font-size: 28rpx;

color: #999;

}

由于我是请求服务器数据,所以js中请求网络源码不能公开,本地源码可参考:https://github.com/LandQ123/littleProgressChooseGoods

 

  • 0
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值