5.1 效果
5.2 业务逻辑
1. 加载分类页面数据
根据接口,获取分类页面数据,要理清楚各层级的关系。
1 /*category/index.js*/ 2 3 /** 4 *获取分类页面数据 5 */ 6 getCates(){ 7 requset({ 8 url:'https://api-hmugo-web.itheima.net/api/public/v1/categories' 9 }) 10 .then(result => { 11 this.Cates = result.data.message; 12 13 //构造左侧的大菜单数据 14 let leftMenuList = this.Cates.map(v=>v.cat_name); 15 // 构建右侧的上平数据 16 let rightContent = this.Cates[0].children; 17 this.setData({ 18 leftMenuList, 19 rightContent 20 }) 21 }) 22 }
2. 点击左侧菜单,右侧数据动态渲染,顶部加入自定义的搜索组件。
(1)先确定搜索栏和左侧菜单栏,右侧商品数据的大小和位置。
左侧菜单和右侧商品数据都采用 scroll-view 组件来实现。左侧占据伸缩盒子的2份,右侧占据5份。先循环读取某一类家电,再读取这类家电下的具体商品。
8行:加一个判断,如果被选中,则添加激活选中效果,即添加.active 这个类
1 <!--pages/category/index.wxml--> 2 <view class="cates"> 3 <SearchInput></SearchInput> 4 <view class="cates_container"> 5 <!-- 左侧菜单 --> 6 <scroll-view scroll-y="{{true}}" class="left_menu"> 7 <view 8 class="menu_item {{index===currentIndex?'active':''}}" 9 wx:for="{{leftMenuList}}" 10 wx:key="*this" 11 > 12 {{item}} 13 </view> 14 </scroll-view> 15 16 <!-- 右侧商品内容 --> 17 <scroll-view scroll-y="{{true}}" class="right_content"> 18 <!-- 循环读取 --> 19 <view class="goods_group" 20 wx:for="{{rightContent}}" 21 wx:for-index="index1" 22 wx:for-item="item1" 23 > 24 <!-- 商品标题 --> 25 <view class="goods_title"> 26 <text class="delimiter">/</text> 27 <text class="title"> {{item1.cat_name}}</text> 28 <text class="delimiter">/</text> 29 </view> 30 <!-- 商品列表 --> 31 <view class="goods_list"> 32 <!-- 循环读取 --> 33 <navigator 34 wx:for="{{item1.children}}" 35 wx:for-index="index2" 36 wx:for-item="item2" 37 wx:key="cat_id" 38 > 39 <!-- 商品图片 --> 40 <image src="{{item2.cat_icon}}" mode="widthFix"></image> 41 <!-- 商品名字 --> 42 <view class="goods_name">{{item2.cat_name}}</view> 43 </navigator> 44 </view> 45 </view> 46 </scroll-view> 47 </view> 48 </view>
13行:容器的高度 = 页面高度 - 搜索组件高度 ~可以让其不被编译
29行:激活选中效果
55行:换行效果 分成三等分,如果商品数超过3份,会换行
62行:text-center 可以是图片和文字居中
1 /* pages/category/index.wxss */ 2 page{ 3 height: 100%; 4 } 5 .cates{ 6 /*继承page的高*/ 7 height: 100%; 8 .cates_container{ 9 /*容器的高度 = 页面高度 - 搜索组件高度*/ 10 /*less中,使用calc的时候要注意 11 ~'内容' 内容会原样输出,不会被less编译 12 */ 13 height: ~'calc( 100vh - 100rpx )'; 14 /*伸缩盒子*/ 15 display: flex; 16 17 .left_menu{ 18 /*伸缩盒子的 子项 默认高度100% flex*/ 19 flex: 2; 20 .menu_item{ 21 height: 80rpx; 22 display: flex; 23 /*水平居中*/ 24 justify-content: center; 25 /*垂直居中*/ 26 align-items: center; 27 font-size: 30rpx; 28 } 29 .active{ 30 color: var(--themeColor); 31 border-left: 5px solid currentColor; 32 } 33 } 34 .right_content{ 35 /*伸缩盒子的 子项 默认高度100% flex*/ 36 flex: 5; 37 38 .goods_group{ 39 /*商品大类名称*/ 40 .goods_title{ 41 height: 80rpx; 42 display: flex; 43 /*水平,垂直居中*/ 44 justify-content: center; 45 align-items: center; 46 font-size: 30rpx; 47 /*斜杆*/ 48 .delimiter{ 49 color: #ccc; 50 padding: 0 10rpx; 51 } 52 .title{ 53 } 54 } 55 /*商品列表*/ 56 .goods_list{ 57 display: flex; 58 /*换行效果 分成三等分,如果商品数超过3份,会换行*/ 59 flex-wrap: wrap; 60 /*水平,垂直居中*/ 61 62 navigator{ 63 /*分成3等份*/ 64 width: 33.3%; 65 /*文本居中*/ 66 text-align: center; 67 image{ 68 width: 50%; 69 } 70 .good_name{} 71 } 72 } 73 } 74 } 75 } 76 }
3. 点击菜单切换不同的商品内容
添加点击事件 handleItemTap,要把当前的index传值给 data-index,方便在js代码中使用当前的index
4.使用缓存技术(商品信息数据量大,使用缓存技术)
在js代码的onLoad事件中,添加缓存技术。
51行: this.Cates = Cates.data; 要注意
77行:要把请求到的数据存储到本地中
1 /* 2 0 web和小程序两者本地存储的区别 3 1 代码不一样: 4 web: localStorage.setItem('key','value') localStorage.getItem('key') 5 小程序:wx-setStorageSync('key','value') wx-getStorageSync('key') 6 2 存的时候有没有做类型转换 7 web: 不管你存入的是什么数据,最终都会调用toString()方法,把数据变为字符串,再存入进去 8 小程序:不存在类型转换,存什么类型的数据数据,获取到的就是什么类型的数据 9 1 先判断本地存储中有没有旧的数据 10 本地存储数据格式{time.Date.now(),data:[...]} 11 2 没有旧数据 直接发送请求 12 3 有旧的数据 同时旧的数据没有过期 直接使用本地的数据即可 13 */
5. 设置每次点击左侧菜单项时,右侧商品的滚动条都在顶部
在scroll-view标签中添加一个属性,scroll-top="{{scrollTop}}",这里不能直接写死(scroll-top="0"),而是通过添加一个变量来实现,这个变量在js代码的data中。
同时在点击事件触发时,更新这个变量
6. 优化接口代码-提取公共路径
在request.js代码中添加如下代码,同时修改其他需要请求数据的页面的js代码,修改其url
7. ⼩程序中⽀持es7的async语法
es7的 async 号称是解决回调的最终⽅案 1. 在⼩程序的开发⼯具中,勾选 es6转es5语法 2. 下载 facebook的regenerator库中的 regenerator/packages/regenerator-runtime/runtime.js 3. 在⼩程序⽬录下新建⽂件夹 lib/runtime/runtime.js ,将代码拷⻉进去 4. 在每⼀个需要使⽤async语法的⻚⾯js⽂件中,都引⼊(不能全局引⼊) import regeneratorRuntime from '../../lib/runtime/runtime';