我们先来看看京东的效果
分析
- 上端导航栏可以放置多个分类,可滑动
- 点击导航栏最右端按钮可以查看所有分类,同时背景模糊
- 内容部分右拉跳转到另外的分类
- 点击分类时导航栏的滑动部分自动滑动到合适的位置
我的实现
代码展示:
js
/** * categoryView.js - 分类页面 */
var fakeData = require('../../common/fakeData.js')
Page( { data: { categories: ['全部'], currentTab: 0, scrollLeftValue: 0, isPickerShow: false, isBgNeed: false, commodities: [] },
navbarTap: function (e) { //将顶部导航栏自动移动到合适的位置 var idx = e.currentTarget.dataset.idx; this.autoScrollTopNav(idx);
//自动收回 if (this.data.isPickerShow) { this.navbarBtnClick(); }
this.setData({ currentTab: idx }) },
/** * 导航栏右侧箭头按钮点击事件 - 切换模糊背景开闭状态以及展开栏开闭状态 */ navbarBtnClick: function(e) { this.data.isBgNeed = !this.data.isPickerShow this.setData({ isBgNeed: this.data.isBgNeed })
this.data.isPickerShow = !this.data.isPickerShow this.setData({ isPickerShow: this.data.isPickerShow, }) },
/** * 页面左右滑动事件 - 构造滑动动画,若当前页面无数据,自动加载,需要完善加载函数 */ swiperChange: function (e) { var idx = e.detail.current; this.autoScrollTopNav(idx);
this.setData({ currentTab: e.detail.current, })
//若无数据,自动加载 if (this.data.commodities[idx].length == 0) { this.downloadMoreItem(); } },
/** * 上拉刷新 */ updateItem: function(e) { var idx = this.data.currentTab; this.data.commodities[idx] = []; this.downloadMoreItem(); },
/** * 下载更多数据 - 涉及后台拉取数据,需完善 */ downloadMoreItem: function(e) { var idx = this.data.currentTab; var commodities = this.data.commodities;
//获取更多数据 commodities[idx] = commodities[idx].concat( fakeData.requestForItemsOfType(commodities[idx].length, 10, this.data.categories[idx]) );
this.setData({ commodities: this.data.commodities })
console.log(this.data.commodities); },
/** * 用于自动调整顶部类别滑动栏滑动距离,使滑动到用户可接受的合适位置,但自适应上还未考虑太周到 * @param {number} idx - The index of currentTap. */ autoScrollTopNav: function (idx) { if (idx <= 2) { this.data.scrollLeftValue = 0; } else { this.data.scrollLeftValue = (idx - 2) * 60; } this.setData({ scrollLeftValue: this.data.scrollLeftValue }) },
/** * 模糊背景点击事件 - 点击模糊背景取消选择 */ bgTap: function(e) { if (this.data.isPickerShow) { this.navbarBtnClick(); } else { return; } },
/** * 商品点击事件 - 待完善 */ itemTap: function(e) { console.log("you selsct type " + this.data.currentTab + " item " + e.currentTarget.dataset.idx); },
/** * 生命周期函数--监听页面加载,在加载的时候抓取数据 */ onLoad: function (options) { //首先获取类别项 this.data.categories = fakeData.requestForCategories(); this.setData({ categories: this.data.categories }) //然后默认请求 全部 分类 for (var i in this.data.categories) { this.data.commodities.push([]); } this.data.commodities[0] = fakeData.requestForItemsOfType(0, 10); console.log(this.data.commodities); this.setData({ commodities: this.data.commodities }) } })
json
{ "navigationBarTitleText": "商城" }
wxml
<!--categoryView.wxml--> <import src="../../common/wxmlTemplate.wxml" />
<!--顶部分类导航条--> <view class=""> <view class="navbar"> <view class="nav-1"> <scroll-view scroll-x="true" class="nav-1-left" scroll-left="{{scrollLeftValue}}" wx:if="{{!isPickerShow}}"> <view wx:for="{{categories}}" data-idx="{{index}}" class="item {{currentTab==index ? 'active' : ''}}" wx:key="unique" bindtap="navbarTap">{{item}}</view> </scroll-view> <view class="nav-1-left" wx:if="{{isPickerShow}}"> <view class="item left2Font">{{categories[currentTab]}}</view> </view> <!-- <view class="blankblock"></view> --> <button class="navbarBtn" bindtap="navbarBtnClick"> <image src="../../resources/返回.png" class="navbarBtn icon {{isPickerShow ? 'active' : ''}}"></image> </button> </view>
<view class="picker" wx:if="{{isPickerShow}}"> <view class="spitLine"></view> <view class="picker-contain"> <view wx:for="{{categories}}" data-idx="{{index}}" class="item {{currentTab==index ? 'active' : ''}}" wx:key="unique" bindtap="navbarTap">{{item}}</view> </view> </view> </view>
<swiper class="itemContainer" bindchange="swiperChange" current="{{currentTab}}"> <block wx:for="{{categories}}" wx:for-item="cItem" wx:key="unique"> <swiper-item> <scroll-view scroll-y="true" bindscrolltolower="downloadMoreItem" bindscrolltoupper="updateItem"> <view class="child" bindtap="itemTap" wx:for="{{commodities[currentTab]}}" data-idx="{{index}}" wx:key="unique" wx:if="{{item.category == cItem || cItem == '全部'}}"> <template is="itemInfoTemplate" data="{{item}}"/> </view> </scroll-view> </swiper-item> </block> </swiper>
<!-- 透明遮盖层 --> <view class="picker-contain-bg {{isPickerShow? 'show' : ''}}" wx:if="{{isBgNeed}}" bindtap="bgTap"></view>
</view>
wxss
@import "../../common/flexGridStyle.wxss"; @import "../../common/itemShowStyle.wxss";
page { display: flex; flex-direction: column; height: 100%; }
.navbar { position: fixed; z-index: 2; background-color: RGB(247, 247, 247); width: 100% }
.nav-1{ flex: none; display: flex; background: #fff; background-color: RGB(247, 247, 247); height: 80rpx; }
.nav-1 .wrapBar { display: flex; }
.nav-1 .item{ position: relative; text-align: center; font-size: 30rpx; line-height: 80rpx; color: gray; display: inline-block; padding-left: 20rpx; padding-right: 20rpx; }
.nav-1 .item.active{ color: black; }
.nav-1 .item.active:after{ content: ""; display: block; position: absolute; bottom: 0; left: 0; right: 0; height: 4rpx; background: black; }
button { background: transparent; }
button::after { border: 0; }
.navbarBtn { flex: 0 0 15%; }
.navbarBtn.icon { transform: rotate(90deg); width: 20rpx; height: 40rpx; }
.navbarBtn.icon.active{ transform: rotate(-90deg); }
.blankblock { flex: 0 0 10%; }
.nav-1-left { white-space: nowrap; overflow: hidden; flex: 0 0 85%; }
.picker { }
.item.left2Font { color: black; }
.spitLine { margin: 0; height: 2rpx; background-color: gray; }
.picker-contain { display: flex; flex-wrap: wrap; justify-content: center; }
.picker-contain-bg { position: fixed; background-color: black; transition: all 1s; width: 100%; height: 100%; z-index: 1; top: 0; opacity: 0 }
.picker-contain-bg.show { opacity: 0.5; }
.picker-contain .item { background-color: RGB(215, 215, 215); border-radius:20px; margin: 20rpx; padding: 50rpx; padding-top: 10rpx; padding-bottom: 10rpx; font-size: 30rpx; color: RGB(161, 161, 161); }
.picker-contain .item.active{ color: black; background-color: RGB(153, 153, 153); }
swiper-item scroll-view { display: inline; }
swiper.itemContainer{ margin-top: 80rpx; height: 1136rpx; }
|