当返回的分类数据比较多的时候该如何处理?
1. 获取分类接口数据
- 获取分类接口数据,并将其拆分。
/**
* 页面的初始数据
*/
data: {
// 左侧分类数据
leftCatesData: [],
// 右侧内容数据
rightContent: []
},
cates: [],
request({ url: "https://api-hmugo-web.itheima.net/api/public/v1/categories" }).then(
result => {
this.cates = result.data.message;
// 构造左侧的大菜单数据
let leftCatesData = this.cates.map(v => v.cat_name);
// 构造右侧的商品数据
let rightContent = this.cates[0].children;
this.setData({
leftCatesData,
rightContent
});
}
)
2. 编写页面结构
<!-- 主体内容 开始 -->
<view class="cates_container">
<!-- 左侧菜单 -->
<scroll-view scroll-y="{{true}}" class="left_menu">
<navigator class="menu_item {{index === currentIndex ? 'active':''}}"
wx:for="{{leftCatesData}}"
wx:key="*this"
bindtap="handleItemClick"
data-index="{{index}}">
<!-- data-index="{{index}}" 在e.currentTarget.dataset中传递索引 index -->
{{item}}
</navigator>
</scroll-view>
<!-- 右侧内容区域 -->
<scroll-view scroll-y="{{true}}" class="right_content">
<view class="goods_group"
wx:for="{{rightContent}}"
wx:for-index="index1"
wx:for-item="item1">
<view class="goods_title">
<text class="delimiter">/</text>
<text class="content">{{item1.cat_name}}</text>
<text class="delimiter">/</text>
</view>
<view class="goods_list">
<navigator
wx:for="{{item1.children}}"
wx:for-index="index2"
wx:for-item="item2"
wx:key="item2.cat_id"
>
<image src="{{item2.cat_icon}}" mode="widthFix"/>
<view class="goods_name">{{item2.cat_name}}</view>
</navigator>
</view>
</view>
</scroll-view>
</view>
<!-- 主体内容 结束 -->
3. 编写样式代码
page {
/* 设置整个page的高度为 100% */
height: 100%;
}
.cates {
height: 100%;
.cates_container {
display: flex;
/* 计算 容器的内容 高度 ~'' 标记将less 原样输出到 wxss 中 100vh 代表视口 100% 的高度*/
height: ~'calc(100vh - 90rpx)';
.left_menu {
flex: 2;
.menu_item {
height: 80rpx;
display: flex;
justify-content: center;
align-content: center;
font-size: 30rpx;
}
.active {
color: var(--themeColor);
border-left: 5rpx solid currentColor;
}
}
.right_content {
flex:5;
.goods_group {
.goods_title {
display: flex;
justify-content: center;
align-content: center;
height: 60rpx;
font-size: 30rpx;
.delimiter {
color: #cccccc;
padding: 0 20rpx;
}
}
.goods_list {
display: flex;
// 允许换行
flex-wrap: wrap;
navigator {
width: 33.333%;
text-align: center;
padding: 20rpx 0;
}
image {
width: 50%;
}
}
}
}
}
}
4. 处理左侧点击与右侧联动
/**
* 处理左侧菜单点击事件
*/
handleItemClick(e) {
// 解构:使用解构赋值的方式将 e.currentTarget.dataset 中的index 解构出来
const { index } = e.currentTarget.dataset;
// 点击左侧右侧也进行切换
let rightContent = this.cates[index].children;
this.setData({
currentIndex: index,
rightContent
})
},
5. 使用缓存技术优化商品分类
5.1 web
中的本地存储和小程序中的本地存储的区别
web
中 :localStorage.setItem("key","item") localStorage.getItem("key")
。小程序中:
wx.getStorageSync("key"); wx.setStorageSync("key","value")
。
5.2 web
中本地存储和小程序中本地存储存的时候有没有做类型转换 ?
web
中不管存入的数据是什么类型的数据,最终都会先调用toString()
,把数据变成了字符串在存进去。小程序中:不存在类型转换的操作,存入什么类型的数据,获取的时候就是什么类型的数据。
5.3 实现步骤
获取本地存储中的数据,判断本地存储中是否存在旧数据?
如果不存在,发送请求重新获取。如果存在,判断数据是否过期,如果数据过期同样需要重新获取。如果以上两种情况都不满足,使用本地存储中的数据。
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
/**
* -1 存的时候有没有做类型转换
* -1.1 web中不管存入的数据是什么类型的数据,最终都会先调用toString() ,把数据变成了字符串在存进去。
* -1.2 小程序中:不存在类型转换的操作,存入什么类型的数据,获取的时候就是什么类型的数据
* 0. web中的本地存储和小程序中的本地存储的区别
* 0.1 web 中 : localStorage.setItem("key","item") localStorage.getItem("key")
* 0.2 小程序中:wx.getStroageSync("key"); wx.setStroageSync("key","value")
* 1. 先判断一下本地存储中有没有旧的数据
* 2. 没有旧数据直接发送请求
* 3. 有旧数据同时旧的数据没有过期,就使用本地存储中的旧数据即可
*/
// 1. 先获取本地存储中的数据(小程序中也是存在本地存储技术的)
const cates = wx.getStorageSync("cates");
if (!cates) {
// 如果不存在 则发送请求
this.getCates();
} else { // 否则存在且事件未过期
if (Date.now() - cates.time > 1000 * 10) {
// 如果旧数据已经过期了需要重新获取
this.getCates();
} else {
this.cates = cates.data;
// 构造左侧的大菜单数据
let leftCatesData = this.cates.map(v => v.cat_name);
// 构造右侧的商品数据
let rightContent = this.cates[0].children;
this.setData({
leftCatesData,
rightContent
});
}
}
},
- 修改获取商品分类数据中的代码,添加将分类数据存储到本地存储的代码。
/**
* 获取商品分类数据
*/
getCates() {
request({ url: "https://api-hmugo-web.itheima.net/api/public/v1/categories" }).then(
result => {
this.cates = result.data.message;
// 发送完请求将数据存入到本地存储中 Date.now() 获取当前的事件戳
wx.setStorageSync("cates", { time: Date.now(), data: this.cates });
// 构造左侧的大菜单数据
let leftCatesData = this.cates.map(v => v.cat_name);
// 构造右侧的商品数据
let rightContent = this.cates[0].children;
this.setData({
leftCatesData,
rightContent
});
}
)
},
6. 右侧商品列表置顶
- 首先滑动右侧至底,点击左侧进行切换时,右侧出现未置顶显示的情况。
6.1 优化解决方案
- 设置
scroll-view
标签的scrollTop
属性为0
;
7. 优化接口代码 - 提取公共接口路径
- 发现接口请求路径中存在公共的部分,需要将其进行抽取。
/**
* export 导出
* @param {*} params
*/
export const request = (params) => {
// 定义公共的 url
const baseUrl = "https://api-hmugo-web.itheima.net/api/public/v1";
return new Promise((resolve, reject) => {
var reqTask = wx.request({
// 解构出参数
...params,
url: baseUrl + params.url,
success: (result) => {
resolve(result);
},
fail: (err) => {
reject(err);
}
});
})
}
8. 小程序支持es7
的 async
语法
es7
的async
号称是解决回调的最终⽅案。
- 在⼩程序的开发⼯具中,勾选
es6
转es5
语法。
勾选`es6`转`es5`语法
下载
facebook
的regenerator
库中的regenerator/packages/regenerator-runtime/runtime.js
。在⼩程序⽬录下新建⽂件夹
lib/runtime/runtime.js
,将代码拷⻉进去。在每⼀个需要使⽤
async
语法的⻚⾯js
⽂件中,都引⼊(不能全局引⼊)。
import regeneratorRuntime from "../../libs/runtime/runtime.js";
- 编写
ES7
代码:
/**
* 获取商品分类数据 ES7 新语法
*/
async getCates() {
const result = await request({ url: "/categories" });
this.cates = result.data.message;
// 发送完请求将数据存入到本地存储中 Date.now() 获取当前的事件戳
wx.setStorageSync("cates", { time: Date.now(), data: this.cates });
// 构造左侧的大菜单数据
let leftCatesData = this.cates.map(v => v.cat_name);
// 构造右侧的商品数据
let rightContent = this.cates[0].children;
this.setData({
leftCatesData,
rightContent
});
}