微信小程序多次请求数据重复的解决方案
今天我来讲一下一组数据如果对其进行了更改但是页面不跟着进行同步渲染怎么办
一、首先我们肯定要知道我要讲的效果是什么
其实呢就是一个新闻列表,然后上面渲染的有图片,有文章标题有文章内容,还有文章发布时间,还有一个是否收藏按钮,一种比较常见的形式。
让我们先看一下要实现的效果
下面看完效果图之后我们来进行代码的实践
既然我们知道要写的效果UI图是什么了 那么我们就可以来写这个效果了
二、第一步静态页面的渲染
1. 既然是静态页面的渲染肯定要先像后端请求数据
我们需要将这个接口封装成一个事件方便后面使用的调用
再简单查看一下这个页面里面data都用什么数据
案例接口信息以及如何将这个信息封装起来如下图所示
我们要在这个小程序文件夹下的 js 文件中书写要写的代码
代码块如下:
// 在index.js文件下
// 封装好这个接口方便后面重复使用的调用
getList(){
wx.request({
url: 'http://localhost:8989/getData?p='+this.data.page,
success:({data})=>{
// 这里声明一个新的空数组用来接收请求到的数据
// 方便对数组进行修改
// 不然对data内的数据进行修改需要使用this.setData显得比较麻烦
let arr=[];
arr= this.data.list.concat(data.data);
// 使用this.setData将修改好的数据赋值给data中要渲染的地方
this.setData({
list: arr
})
}
})
},
写好这个请求接口之后直接让页面初次加载的onLoad函数调用该事件即可 具体写法入下
这样一个请求数据就完了然后我们的数据也已经拿到了
差的就是一个渲染
2. 页面渲染就需要HTML结合JS数据一起使用了
我相信HTML的具体渲染应该没有什么好讲的
首先肯定是打开文件夹下的这个wxml文件
在这个页面进行渲染数据即可
当然微信小程序和原生HTML的语法方式还有有区别的 具体代码如下:
<!-- 使用wx:for进行绑定数据循环 以及wx:key绑定key值防止出现混乱 -->
<!-- 这里的View标签类似与原生HTML的div标签 -->
<view wx:for="{{list}}" wx:key="key" class="content_">
<view class="left_">
<!-- 渲染图片 -->
<!-- 这里itme是微信小程序自己编写的item默认值也可以wx:for-item修改使用名字的值 -->
<!-- image标签类似于之前的img标签 但是image是一个双标签 而img是一个单标签 -->
<image class="left_image" data-id="{{item.id}}" catchtap="goDetail" src="{{item.imgUrl}}"></image>
</view>
<view class="right_">
<!-- 渲染标题 -->
<!-- 这里的text类似于原生HTML的span表签 text标签内部不能包含其他标签 -->
<text class="right_title">{{item.title}}</text>
<!-- 渲染标题 -->
<text class="right_content">{{item.content}}</text>
<view class="right_collect">
<!-- 未收藏 -->
<!-- 这里用if判断根据请求到的数据进行判断 -->
<!-- 如果数据为false则显示未收藏 -->
<image data-id='{{item.id}}' data-num="0" catchtap="setCollect" wx:if="{{!item.collect}}" src="/Font/收藏.png"></image>
<!-- 已经收藏 -->
<!-- 如果数据为true则显示收藏 -->
<image data-id='{{item.id}}' data-num="1" catchtap="setCollect" wx:if="{{item.collect}}" src="/Font/收藏_active.png"></image>
</view>
</view>
</view>
上面是具体页面渲染的代码块
3. 小程序的语法跟原生HTML语法有什么不同
因为这个是小程序的语法所以跟原生HTML的语法不同
我们简单做个表格比较一下
WXML语法 | HTML语法 |
view 标签 | div 标签 |
text 标签 | span 标签 |
image 标签 | img 标签 |
check、input、radio 标签 | input type(check、text、radio) 标签 |
picker range="{{area}}" 标签 | select > option 标签 |
navigator 标签 | a 标签 |
icon 标签 | i 标签 |
上面的表格就是一些基础标签的对比
可以看到WXML的语法还是很生疏的
这就是对小程序语法的一个简介的描述
三、第二步就需要来做这个收藏与未收藏的效果
既然都要写收藏与未收藏的渲染了那么我们应该知道收藏与未收藏的依据是什么呢这个时候我们可以查看一下接口返回的数据中有没有这个依据
1. 收藏的依据查看
我们可以使用 console.log() 在控制台输出查看请求到的数据 小程序界面的左上角有调试器按钮 点击之后可以进入控制台查看数据
上面控制台中显示的请求到的数据也可以看到有个collect属性并且它的值还是flase布尔值然后也可以到后端看一看就可以知道这个collect或者别的接口别的属性名它属于是一个收藏依据当然它不一定是一个布尔值,也有可能是1或者任何数据来表示这个问题主要还是带看后端的写法然后下面的数据渲染就可以用这个数据来判断是否收藏
<view class="right_collect">
<!-- 未收藏 -->
<!-- 这里用if判断根据请求到的数据进行判断 -->
<!-- 如果数据为true则显示收藏 -->
<image data-id='{{item.id}}' data-num="0" catchtap="setCollect" wx:if="{{!item.collect}}" src="/Font/收藏.png"></image>
<!-- 已经收藏 -->
<!-- 如果数据为false则显示未收藏 -->
<image data-id='{{item.id}}' data-num="1" catchtap="setCollect" wx:if="{{item.collect}}" src="/Font/收藏_active.png"></image>
</view>
2. 通过收藏应该触发什么事件
上图中用catchcap调用事件并且使用data-id和data-num传了两个参数
因为两行代码调用的同一个事件所以需要用用来分辨一下所以用了一个传了一个num如果是0则代表收藏如果是1就代表取消收藏
既然参数都传了我们肯定需要在JS事件内接收一下当然微信小程序事件参数接收跟之前也是大不相同的下面让我们看一下是如何接收参数的
// 点击事件
setCollect(e){
// 当前点击数据的标识id
let id=e.currentTarget.dataset.id
// 当前点击数据判断是要调用收藏还是要取消收藏的
let num=e.currentTarget.dataset.num
// console.log(id)
if(num==0){
// 调用收藏接口
this.setClect(id)
}else{
// 调用取消收藏接口
this.setClects(id)
}
// console.log(this.data.list);
// 再次调用接口来更改当前数据
// 否则数据不会同步更新
this.gitList();
}
上面JS代码块可以看到在微信小程序中接收参数使用的是默认参数e下面的currentTarget下面的dataset中取到传递的id和num的
后面重新调用来更改当前数据否则数据不会同步更新
这些就是普通的JS与WXML的基本交互
然后在来看看普通的JS与WXML交互之后触发的效果
调用收藏接口以及取消收藏接口
(1). 收藏接口
下面看看收藏接口是怎么写的
// 收藏
setClect(id){
wx.request({
// 根据指定数据标识进行收藏
url: 'http://localhost:8989/collect?id='+id,
success:(res)=>{
// 因为这里只是对后端的数据进行了改变
// 要想本地的数据也改变则需要自己手动更改一下
this.data.list.forEach((item)=>{
//判断查找到当前的数据
if(item.id==id){
item['collect']=true;
}
})
}
})
}
因为这里只是对后端的数据进行了改变要想本地的数据也改变则需要自己手动更改一下
(2). 取消收藏接口
下面看看收藏接口是怎么写的
// 取消收藏
setClects(id){
wx.request({
// 根据指定数据标识进行收藏
url: 'http://localhost:8989/cancelCollect?id='+id,
success:(res)=>{
// 因为这里只是对后端的数据进行了改变
// 要想本地的数据也改变则需要自己手动更改一下
this.data.list.forEach((item)=>{
//判断查找到当前的数据
if(item.id==id){
item['collect']=false;
}
})
}
})
}
同样这里只是对后端的数据进行了改变要想本地的数据也改变则需要自己手动更改一下
但是这里基本上就全部完成了但是还有一些BUG
四、总结
就比如说由于我们多次调用那个请求数据接口会出现数据重复出现
首先原因是因为我们用的 concat数组拼接方法 就会把每一次请求到的数据进行拼接到一块,像这个时候我们就需要写一个数组去重方法来将这些重复的数据去重掉
具体的写法如下
// 封装好这个接口方便后面重复使用的调用
getList(){
wx.request({
url: 'http://localhost:8989/getData?p='+this.data.page,
success:({data})=>{
// 这里声明一个新的空数组用来接收请求到的数据
// 方便对数组进行修改
// 不然对data内的数据进行修改需要使用this.setData显得比较麻烦
let arr=[];
arr= this.data.list.concat(data.data);
// 去重
let obj = {}
arr = arr.reduce((preVal,curVal) => {
obj[curVal.id] ? "" : obj[curVal.id] = preVal.push(curVal)
return preVal
},[])
console.log(arr)
// 使用this.setData将修改好的数据赋值给data中要渲染的地方
this.setData({
list: arr
})
}
})
}
有了这个去重之后就不用害怕页面数据渲染不同步了
为了让页面同步所以需要重复调用接口数据
这就是简单的一个小程序还有一些BUG处理
讲完了,下课
其他文章:点击跳转