小程序左右列表联动优化版(简单易懂)

项目地址:https://github.com/Creambb/linkScroll

最近通过做一个商城的项目实战学习小程序,目前市场上大部分的商城列表都使用了菜单的左右联动功能,因为自己想做好这个项目,所以在实现了以后还进行了一下优化,想记录下来。

话不多说,直接上代码。建议下载github上的项目,里面内容比较全,有图片,看得更清晰

效果图

wxml

<view class="contain">
	<view id="header">
		<!-- 这是我写的头部组件,可以忽略 -->
		<header title="Bingo" />
	</view>
	<view id="searchBox" class="searchBox">
		<view class="search">
			<image src=""></image>
			<input placeholder="搜索商品"></input>
			<image src=""></image>
		</view>
		<button class="search-button">搜索</button>
	</view>
	<view class='main'>
		<view class='left'>
			<scroll-view scroll-y="true" class="leftScroll" scroll-into-view="true" scroll-with-animation="true">
				<block wx:for="{{dataList}}" wx:for-list="item" wx:for-index="index" wx:key="index">
					<view class="{{currentActiveIndex == index?'leftActive':'leftInactive'}}" data-index="{{index}}" data-id='{{item.id}}' bindtap='changeLeftMenu'>
						<text>{{item.navTitle}}</text>
					</view>
				</block>
			</scroll-view>
		</view>
		<view class='right'>
			<!-- 
          1. scroll-into-view="{{'inToview'+rigId}}"和下面的id="{{'inToview'+item.id}}"对应
          2. rigId为变量,设置rigId的值,列表会滑动到对应的id
          3. 注意:scroll-into-view的属性不能以数字开头
      -->
			<scroll-view scroll-y="true" style="height: 1100rpx" bindscroll="scroll" scroll-top="{{scrollTop}}" scroll-into-view="{{'inToview'+rigId}}" scroll-with-animation="true">
				<block wx:for="{{dataList}}" wx:for-list="item" wx:for-index="index" wx:key="index">
					<view wx:if="{{item.goodsList.length != 0}}" class='itemTitle' id="{{'inToview'+item.id}}">{{item.navTitle}}</view>
					<view class='listItem' data-id='{{item.id}}'>
						<block wx:for="{{item.goodsList}}" wx:for-index="idx" wx:key="idx">
							<view class='listItemSub' data-text="{{}}">
								<view class='img'>
									<!-- 图片出不来就用灰色块代替了 -->
									<!-- <image src='{{item.goodsUrl}}'></image> -->
									<image src=''></image>
								</view>
								<view class='listText'>
									<text>{{item.goodsName}}</text>
									<text class='money'>¥{{item.shopPrice}}</text>
									<view>
										<text>已售{{item.saleNum}}</text>
										<image class="add-image" src="../../images/goods/add.svg"></image>
									</view>
								</view>
							</view>
						</block>
					</view>
				</block>
			</scroll-view>
		</view>
	</view>
</view>

xcss

::-webkit-scrollbar {
  width: 0;
  height: 0;
  color: transparent;
}

::-webkit-scrollbar-track {
  height: 20rpx;
  color: black;
}

page {
  width: 100%;
  height: 100%;
}

.contain {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  /* padding-top: 140rpx; */
  padding-bottom: 100rpx;
}

.leftActive {
  color: red;
  background-color: #fff;
}

.leftInactive {
  background-color: #F8F8F8;
}

.searchBox {
  display: flex;
  background-color: rgba(219, 219, 221, 1);
  align-items: center;
  height: 60rpx;
  padding: 10rpx 0;
  position: fixed;
  left: 0;
  width: 100%;
  z-index: 1;
}

.searchBox .search-button {
  /* width: auto; */
  min-height: 50rpx;
  line-height: 50rpx;
  width: 15%;
  padding: 0;
  line-height: 1;
  font-size: 30rpx;
}

.search {
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* height: 50rpx; */
  border-radius: 30rpx;
  margin-left: 20rpx;
  padding: 0 20rpx;
  background-color: white;
  width: 65%;
}

.search input {
  font-size: 30rpx;
  width: 100%;
}

.search text {
  color: gainsboro;
  font-family: monospace;
  font-size: 30rpx;
  line-height: 46rpx;
}

.search image {
  padding: 0 5rpx;
  width: 46rpx;
  height: 46rpx;
}

.main {
  display: flex;
  padding-top: 80rpx;
}

.left {
  width: 25%
}

.left view {
  width: 180rpx;
  height: 70rpx;
  padding-top: 30rpx;
  text-align: center;
  font-size: 32rpx;
}

.right {
  width: 75%;
}

.listItemSub {
  display: flex;
}

.listItem .img {
  width: 200rpx;
  height: 200rpx;
  text-align: center;
  padding-top: 10rpx;
}

.listItem .img image {
  width: 80%;
  height: 80%;
  background-color: #eee;
}

.itemTitle {
  font-size: 32rpx;
  padding-left: 20rpx;
  padding-top: 10rpx;
  color: gray;
}

.listItem .listText {
  display: flex;
  flex-direction: column;
  margin-top: 6rpx;

  width: calc(100% - 200rpx);
}

.listItem .listText view {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
}

.listItem .listText text {
  font-size: 34rpx;
  margin-top: 10rpx;
}

.listItem .listText .money {
  color: red;
}

.listItem .listText view text {
  font-size: 28rpx;
  color: silver;
  margin-right: 60rpx;
  /* add  */
  min-width: 80px;
  display: inline-block;
}

.listItem .listText view button {
  background-color: red;
  color: white;
  padding-right: 8px;
  padding-left: 8px;
  padding-top: 0px;
}

.add-image {
  width: 40rpx;
  height: 40rpx;
  padding-right: 20rpx;
}

.leftScroll {
  height: 100%;
  width: 180rpx;
  background: #F8F8F8;
}

js

Page({

  data: {
    // 数据列表
    dataList: [
      {
        id: "01",
        navTitle: "活动",
        goodsList: [{
          id: 1,
          goodsUrl: "../../images/goods/pencil01.jpg",
          goodsName: "晨光优品中性笔",
          typeList: ['粉红色', '淡蓝色', '淡黄色'],
          shopPrice: 3,
          saleNum: 20,
        },
        {
          id: 2,
          goodsUrl: "../../images/goods/pencil02.jpg",
          goodsName: "得力彩色中性笔",
          typeList: ['白色', '橘色'],
          shopPrice: 5.2,
          saleNum: 20,
        },
        {
          id: 3,
          goodsUrl: "../../images/goods/pencil03.jpg",
          goodsName: "得力糖果中性笔",
          shopPrice: 12,
          saleNum: 20,
        },
        {
          id: 4,
          goodsUrl: "../../images/goods/pencil04.jpg",
          goodsName: "按压式花边修正带",
          shopPrice: 6.9,
          saleNum: 20,
        },
        {
          id: 5,
          goodsUrl: "../../images/goods/pencil05.jpg",
          goodsName: "得力文具便利贴",
          shopPrice: 4,
          saleNum: 20,
        }
        ],
      },
      {
        id: "02",
        navTitle: "新品",
        goodsList: [{
          id: 21,
          goodsUrl: "../../images/goods/pencil01.jpg",
          goodsName: "晨光优品中性笔",
          shopPrice: 3,
          saleNum: 20,
        },
        {
          goodsUrl: "../../images/goods/pencil02.jpg",
          goodsName: "得力彩色中性笔",
          shopPrice: 5.2,
          saleNum: 20,
          id: 22,
        },
        {
          id: 4,
          goodsUrl: "../../images/goods/pencil04.jpg",
          goodsName: "按压式花边修正带",
          shopPrice: 6.9,
          saleNum: 20,
        },
        {
          id: 5,
          goodsUrl: "../../images/goods/pencil05.jpg",
          goodsName: "得力文具便利贴",
          shopPrice: 4,
          saleNum: 20,
        }
        ],
      },
      {
        id: "03",
        navTitle: "推荐",
        goodsList: [{
          goodsUrl: "../../images/goods/pencil01.jpg",
          goodsName: "晨光优品中性笔",
          shopPrice: 3,
          saleNum: 20,
          id: 31,
        },
        {
          goodsUrl: "../../images/goods/pencil02.jpg",
          goodsName: "得力彩色中性笔",
          shopPrice: 5.2,
          saleNum: 20,
          id: 32,
        },
        {
          id: 4,
          goodsUrl: "../../images/goods/pencil04.jpg",
          goodsName: "按压式花边修正带",
          shopPrice: 6.9,
          saleNum: 20,
        },
        {
          id: 5,
          goodsUrl: "../../images/goods/pencil05.jpg",
          goodsName: "得力文具便利贴",
          shopPrice: 4,
          saleNum: 20,
        },
        ],
      },
      {
        id: "04",
        navTitle: "晨光系列",
        goodsList: [{
          goodsUrl: "../../images/goods/pencil01.jpg",
          goodsName: "晨光优品中性笔",
          shopPrice: 3,
          saleNum: 20,
          id: 41,
        },
        {
          id: 4,
          goodsUrl: "../../images/goods/pencil04.jpg",
          goodsName: "晨光按压式花边修正带",
          shopPrice: 6.9,
          saleNum: 20,
        },
        {
          id: 5,
          goodsUrl: "../../images/goods/pencil05.jpg",
          goodsName: "晨光文具便利贴",
          shopPrice: 4,
          saleNum: 20,
        },
        ],
      },
      {
        id: "05",
        navTitle: "文具专区",
        goodsList: [{
          goodsUrl: "../../images/goods/pencil01.jpg",
          goodsName: "晨光优品中性笔(美)",
          shopPrice: 3,
          saleNum: 20,
          id: 61,
        },
        {
          goodsUrl: "../../images/goods/pencil02.jpg",
          goodsName: "得力彩色中性笔",
          shopPrice: 5.2,
          saleNum: 20,
          id: 62,
        },
        ],
      },
      {
        id: "06",
        navTitle: "精品专区",
        goodsList: [{
          goodsUrl: "../../images/goods/pencil01.jpg",
          goodsName: "晨光优品中性笔",
          shopPrice: 3,
          saleNum: 20,
          id: 1,
        },
        {
          goodsUrl: "../../images/goods/pencil02.jpg",
          goodsName: "得力彩色中性笔",
          shopPrice: 5.2,
          saleNum: 20,
          id: 2,
        },
        ],
      },
    ],
    searchHeight: 0,   // 搜索框高度
    currentActiveIndex: 0,   // 当前菜单索引
    isClickMenu: false, // 是否点击菜单
    proListToTop: [],  // 记录每一个类型的列表道顶部的距离
  },

  onLoad: function (options) {
    this.getEleHeight();
  },

  getEleHeight() {
    var searchHeight, proListToTop = [];

    // 搜索框所占据的高度,在后续滑动时需要减掉该高度
    wx.createSelectorQuery().select("#searchBox").boundingClientRect(res => {
      searchHeight = res.height
      // 回调函数是异步的,所以需要在方法里面更新数据
      this.setData({
        searchHeight: searchHeight,
      })
    }).exec()

    // 记录每一个类型的列表道顶部的距离
    wx.createSelectorQuery().selectAll('.itemTitle').boundingClientRect((rects) => {
      rects.forEach((rect) => {
        proListToTop.push(rect.top.toFixed(2) - this.data.searchHeight);
      })
      this.setData({
        proListToTop: proListToTop,
      })
    }).exec()

  },

  //滚动触发
  scroll: function (e) {
    // 若滑动是点击菜单触发的,则不进行判断;
    if (!this.data.isClickMenu) {
      // 获取滚动的高度
      var scrollTop = e.detail.scrollTop;
      var proListToTop = this.data.proListToTop;
      var currentActiveIndex;
      for (let i = 0; i < proListToTop.length; i++) {
        // 根据滑动距离判断当前处于哪个菜单索引
        if (e.detail.scrollTop < proListToTop[i] && i !== 0 && e.detail.scrollTop > proListToTop[i - 1]) {
          this.setData({
            currentActiveIndex: i - 1,
          })
        }
      }
    }
    // 将点击菜单状态还原为false
    this.setData({
      isClickMenu: false,
    })
  },

  //点击左边菜单事件
  changeLeftMenu: function (e) {
    // 当前点击的导航对应的右列表id
    var rigId = e.currentTarget.dataset.id;
    // 当前导航索引
    var index = e.currentTarget.dataset.index;
    // 点击当前导航索引,不作处理
    if (this.data.currentActiveIndex === index) {
      return;
    }
    this.setData({
      rigId: rigId,
      // 设置选中id
      currentActiveIndex: index,
      // 是否点击
      isClickMenu: true
    })
  },

})
  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微信小程序实现左右列表联动的代码可参考以下示例: wxml部分: ```html <view class="container"> <view class="left"> <scroll-view scroll-y="{{true}}" scroll-into-view="{{scrollIntoView}}" scroll-with-animation="{{true}}" class="scroll-view-left"> <block wx:for="{{leftList}}" wx:key="index"> <view class="item {{leftIndex == index ? 'active' : ''}}" data-index="{{index}}" bindtap="handleLeftItemTap">{{item}}</view> </block> </scroll-view> </view> <view class="right"> <scroll-view scroll-y="{{true}}" scroll-into-view="{{scrollIntoView}}" scroll-with-animation="{{true}}" class="scroll-view-right"> <block wx:for="{{rightList[leftIndex].children}}" wx:key="index"> <view class="item" data-index="{{index}}" bindtap="handleRightItemTap">{{item}}</view> </block> </scroll-view> </view> </view> ``` js部分: ```javascript Page({ data: { leftIndex: 0, scrollIntoView: '', leftList: ['分类1', '分类2', '分类3'], rightList: [ { name: '分类1', children: ['子分类1', '子分类2', '子分类3'] }, { name: '分类2', children: ['子分类4', '子分类5', '子分类6'] }, { name: '分类3', children: ['子分类7', '子分类8', '子分类9'] } ] }, handleLeftItemTap: function(e) { const index = e.currentTarget.dataset.index; this.setData({ leftIndex: index, scrollIntoView: `right-item-${index}-0` }); }, handleRightItemTap: function(e) { const index = e.currentTarget.dataset.index; wx.showToast({ title: `点击了${this.data.rightList[this.data.leftIndex].children[index]}`, icon: 'none' }); } }) ``` 其中,`leftList` 为左侧列表,`rightList` 为右侧列表,`leftIndex` 为左侧选中的索引,`scrollIntoView` 为滚动到的位置。 在左侧列表中点击某个分类时,将 `leftIndex` 更新为当前索引并将 `scrollIntoView` 更新为对应右侧列表中第一个子分类的 `id`,从而实现左侧列表与右侧列表联动。 右侧列表中点击某个子分类时,可以触发相应的逻辑操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值