将浏览记录缓存并渲染到个人页面
在详情页中进行存储,只要用户进入过详情页,就表示用户观看过这条新闻
代码逻辑是:只要用户进入详情页,就把详情页本身在进行网络数据获取时拿到的缩略图、标题、作者、cid、sid等信息保存到一个提前写好的函数saveHistory中,保存这些信息就是通过在这个函数中调用StorageSync方法完成的
在网络请求方法中调用saveHistory方法,这样,在一进入页面,进行网络请求的同时,相关信息就被保存在内存中了
methods:{
getDetail(){
uni.request({
url:"https://ku.qingnian8.com/dataApi/news/detail.php",
// 这里url携带的参数就是cid和id,而且data的参数就是一个对象,options也是一个对象
// options直接放到这里来,就是这里要携带的参数
data:this.options,
success: res=>{
console.log(res);
// 解决微信小程序图片显示不全的问题
// res.data.content = res.data.content.replace(/<img/gi,'<img style="max-width: 100%"')
// 将接口获取到的数据data赋值给自定义变量detail,在页面中就可以拿到值了
this.detail = res.data;
// 调用数据缓存方法,一进入页面,就将信息保存到缓存中
this.saveHistory();
uni.setNavigationBarTitle({
title:this.detail.title
})
}
})
},
saveHistory(){
//先判断内存中有没有这个值再保存,否则旧值会被新值覆盖,使用追加值保存
// 先获取缓存中是否存在historyArr
// 或运算:一个为真就为真,全假则为假,遇真则停
// 如果存在historyArr,就向里面追加一个值,没有historyArr就保存一个空数组
let historyArr = uni.getStorageSync("historyArr") || []
let item={
id:this.detail.id,
classid:this.detail.classid,
picurl:this.detail.picurl,
title: this.detail.title,
looktime:Date.now()
}
historyArr.unshift(item)
uni.setStorageSync("historyArr", historyArr)
}
}
}
随意点击一条信息进入详情页,数据已经被保存好了
在数据缓存的页面可以看到已经有两条缓存了,现在还有一个问题,重复点击同一条数据会多次保存,所以需要做去重
视频里没有解决这个问题,接下来就是渲染数据到user页面 user页面的逻辑:写一个方法读取缓存数据,如果有数据,就返回数据,没有就返回一个空数组,然后把读取到的值保存到data,在onload中调用这个方法,一进入页面就调用这个方法,最后是在标签中拿到data里的数据,渲染在页面中
<template>
<view class="user">
<view class="top">
<image src="../../static/images/history.png" mode=""></image>
<text>浏览历史</text>
</view>
<view class="content">
<view class="row" v-for="item in listArr">
<newsStyle :item="item" @click.native="goDetail"></newsStyle>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
listArr:[]
};
},
onLoad() {
this.getData()
},
methods:{
goDetail(){
uni.navigateTo({
url:"/pages/detail/detail"
})
},
// 获取缓存浏览记录
getData(){
// 如果缓存中有数据就读取出来,如果没有就返回一个空数组
let hisArr = uni.getStorageSync("historyArr") || []
this.listArr = hisArr
}
}
}
</script>
<style lang="scss">
.user{
.top{
padding: 50rpx 0;
background: #f8f8f8;
color: #555;
display: flex;
// 使图标和文字垂直显示
flex-direction: column;
// 下面两句使图标和文字居中显示
justify-content: center;
align-items: center;
image{
width: 150rpx;
height: 150rpx;
}
.text{
font-size: 38rpx;
color: #555;
padding: 20rpx;
}
}
}
</style>
现在点击新闻是不能跳转的,因为还没有传参,在点击事件中传参,然后在跳转方法里接收参数
<template>
<view class="user">
<view class="top">
<image src="../../static/images/history.png" mode=""></image>
<text>浏览历史</text>
</view>
<view class="content">
<view class="row" v-for="item in listArr">
<newsStyle :item="item" @click.native="goDetail(item)"></newsStyle>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
listArr:[]
};
},
onLoad() {
this.getData()
},
methods:{
goDetail(item){
uni.navigateTo({
url:`/pages/detail/detail?cid=${item.classid}&id=${item.id}`
})
},
// 获取缓存浏览记录
getData(){
// 如果缓存中有数据就读取出来,如果没有就返回一个空数组
let hisArr = uni.getStorageSync("historyArr") || []
this.listArr = hisArr
}
}
}
</script>
现在在个人中心点击浏览记录,就又能进入详情页了
处理findindex索引数据去重和优化细节
无论在首页点的新闻,还是在个人中心点的新闻,只要点进去详情页,就会被保存,这样就会重复多次的保存同一条新闻
处理逻辑:详情页里的文章保存了id,这是这篇文章的唯一标识符,保存在storage里的数据也保存了id,可以通过对比id来判断这一篇文章有没有被保存,如果比对出来了,证明已经被保存过了,那就把原本保存的那一条新闻删掉,然后再把新的数据追加进去,还有观看时间也不一样,也可以通过比对观看时间来判断
// 判断获取到的值有没有被保存过,如果有,就删掉之前的,保存新的
// 通过findIndex来找是否数组中包含某个值
// findindex返回值:比对成功就返回比对值在数组中的索引,没有比对成功就返回-1
let index=historyArr.findIndex(i=>{
return i.id==this.detail.id
})
// 开始判断:如果这个值之前被保存过,就splice删掉他
// 大于0表示有值,等于0,是因为数组的第一个元素索引值是0
//如果这一条新闻之前保存过,就删掉他
// 接下来就是按代码顺序正常在内存中插入这条数据进行保存
//如果这一条新闻之前没有保存过,findIndex返回值是-1,不走这个判断
// 会自动按正常代码流程保存这一条数据
if(index>=0){
historyArr.splice(index, 1)
}
现在就实现了去重detail页面全部代码如下:
<template>
<view class="detail">
<view class="title">{{detail.title}}</view>
<view class="info">
<view class="author">编辑: {{detail.author}}</view>
<!-- <view class="time">发布日期: {{detail.posttime}}</view> -->
<uni-dateformat :date="detail.posttime*1000" format="yyyy/MM/dd hh:mm:ss"></uni-dateformat>
</view>
<view class="content">
<!-- <view v-html="detail.content"></view> -->
<rich-text :nodes="detail.content"></rich-text>
</view>
<view class="description">
声明:本站的内容均采集自腾讯新闻,如果侵权请联系xxx进行整改删除,本站进行了内容采集不代表本站及作者观点,若有侵权请及时联系管理员,谢谢支持
</view>
</view>
</template>
<script>
export default {
data() {
return {
options: null,
detail:{}
};
},
onLoad(e) {
this.options = e;
// 在这里调用获取网络数据的方法,一进去页面就能执行
this.getDetail();
},
methods:{
getDetail(){
uni.request({
url:"https://ku.qingnian8.com/dataApi/news/detail.php",
// 这里url携带的参数就是cid和id,而且data的参数就是一个对象,options也是一个对象
// options直接放到这里来,就是这里要携带的参数
data:this.options,
success: res=>{
console.log(res);
// 解决微信小程序图片显示不全的问题
// res.data.content = res.data.content.replace(/<img/gi,'<img style="max-width: 100%"')
// 将接口获取到的数据data赋值给自定义变量detail,在页面中就可以拿到值了
this.detail = res.data;
// 调用数据缓存方法,一进入页面,就将信息保存到缓存中
this.saveHistory();
uni.setNavigationBarTitle({
title:this.detail.title
})
}
})
},
saveHistory(){
//先判断内存中有没有这个值再保存,否则旧值会被新值覆盖,使用追加值保存
// 先获取缓存中是否存在historyArr
// 或运算:一个为真就为真,全假则为假,遇真则停
// 如果存在historyArr,就向里面追加一个值,没有historyArr就保存一个空数组
let historyArr = uni.getStorageSync("historyArr") || []
let item={
id:this.detail.id,
classid:this.detail.classid,
picurl:this.detail.picurl,
title: this.detail.title,
looktime:Date.now()
}
// 判断获取到的值有没有被保存过,如果有,就删掉之前的,保存新的
// 通过findIndex来找是否数组中包含某个值
// findindex返回值:比对成功就返回比对值在数组中的索引,没有比对成功就返回-1
let index=historyArr.findIndex(i=>{
return i.id==this.detail.id
})
// 开始判断:如果这个值之前被保存过,就删掉他
// 之所以要等于0,是因为数组的第一个元素索引值是0
//如果这一条新闻之前保存过,就删掉他
// 剩下的,就是按代码顺序正常在内存中插入这条数据进行保存
//如果这一条新闻之前没有保存过,findIndex返回值是-1,不走这个判断
// 会自动按正常代码流程保存
if(index>=0){
historyArr.splice(index, 1)
}
// 将值保存到item中
historyArr.unshift(item)
uni.setStorageSync("historyArr", historyArr)
}
}
}
</script>
<style lang="scss">
.detail {
padding: 30rpx;
.title {
font-size: 46rpx;
color: #333;
}
.info {
background: #f6f6f6;
padding: 20rpx 20rpx;
font-size: 25rpx;
color: #666;
// 加盒模型,使作者和时间部分左右对齐
display: flex;
justify-content: space-between;
margin: 40rpx 0;
}
// 内容部分
.content {
padding-bottom: 50rpx;
[alt]{
max-width: 100%;
}
}
// 声明部分
.description {
background: #fef0f0;
font-size: 26rpx;
padding: 20rpx;
color: #f89898;
line-height: 1.8em;
}
}
</style>
但是还有一个问题,个人中心显示的数据之前是在onload中进行加载的,onload这个方法只有在页面刷新时才加载数据,这就出现一个问题,每次点击观看的新闻,如果不刷新页面,直接点到个人中心去看,是没有数据的,要重新在个人中心刷新页面,观看过的数据才会被加载出来
在首页点了其他新闻,进入详情页之后,退出来,点个人,发现还是原来的数据,就是因为onload的原因,在user页面把onload方法改成onshow即可,这样每次一进入个人页面,浏览过的新闻就会在onshow中被加载出来
<template>
<view class="user">
<view class="top">
<image src="../../static/images/history.png" mode=""></image>
<text>浏览历史</text>
</view>
<view class="content">
<view class="row" v-for="item in listArr">
<newsStyle :item="item" @click.native="goDetail(item)"></newsStyle>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
listArr:[]
};
},
onShow() {
this.getData()
},
methods:{
goDetail(item){
uni.navigateTo({
url:`/pages/detail/detail?cid=${item.classid}&id=${item.id}`
})
},
// 获取缓存浏览记录
getData(){
// 如果缓存中有数据就读取出来,如果没有就返回一个空数组
let hisArr = uni.getStorageSync("historyArr") || []
this.listArr = hisArr
}
}
}
</script>
还有一个小问题,没有必要把用户浏览的新闻无限制的全部存到缓存中,存个10条就够了,在detail页面中,把存储的数据截取前10条出来保存就行了
//用户浏览记录没有必要全部保存,只保存最近的10条数据就够了
historyArr=historyArr.splice(0,10)
detail页面的全部代码:
<template>
<view class="detail">
<view class="title">{{detail.title}}</view>
<view class="info">
<view class="author">编辑: {{detail.author}}</view>
<!-- <view class="time">发布日期: {{detail.posttime}}</view> -->
<uni-dateformat :date="detail.posttime*1000" format="yyyy/MM/dd hh:mm:ss"></uni-dateformat>
</view>
<view class="content">
<!-- <view v-html="detail.content"></view> -->
<rich-text :nodes="detail.content"></rich-text>
</view>
<view class="description">
声明:本站的内容均采集自腾讯新闻,如果侵权请联系xxx进行整改删除,本站进行了内容采集不代表本站及作者观点,若有侵权请及时联系管理员,谢谢支持
</view>
</view>
</template>
<script>
export default {
data() {
return {
options: null,
detail:{}
};
},
onLoad(e) {
this.options = e;
// 在这里调用获取网络数据的方法,一进去页面就能执行
this.getDetail();
},
methods:{
getDetail(){
uni.request({
url:"https://ku.qingnian8.com/dataApi/news/detail.php",
// 这里url携带的参数就是cid和id,而且data的参数就是一个对象,options也是一个对象
// options直接放到这里来,就是这里要携带的参数
data:this.options,
success: res=>{
console.log(res);
// 解决微信小程序图片显示不全的问题
// res.data.content = res.data.content.replace(/<img/gi,'<img style="max-width: 100%"')
// 将接口获取到的数据data赋值给自定义变量detail,在页面中就可以拿到值了
this.detail = res.data;
// 调用数据缓存方法,一进入页面,就将信息保存到缓存中
this.saveHistory();
uni.setNavigationBarTitle({
title:this.detail.title
})
}
})
},
saveHistory(){
//先判断内存中有没有这个值再保存,否则旧值会被新值覆盖,使用追加值保存
// 先获取缓存中是否存在historyArr
// 或运算:一个为真就为真,全假则为假,遇真则停
// 如果存在historyArr,就向里面追加一个值,没有historyArr就保存一个空数组
let historyArr = uni.getStorageSync("historyArr") || []
let item={
id:this.detail.id,
classid:this.detail.classid,
picurl:this.detail.picurl,
title: this.detail.title,
looktime:Date.now()
}
// 判断获取到的值有没有被保存过,如果有,就删掉之前的,保存新的
// 通过findIndex来找是否数组中包含某个值
// findindex返回值:比对成功就返回比对值在数组中的索引,没有比对成功就返回-1
let index=historyArr.findIndex(i=>{
return i.id==this.detail.id
})
// 开始判断:如果这个值之前被保存过,就删掉他
// 之所以要等于0,是因为数组的第一个元素索引值是0
//如果这一条新闻之前保存过,就删掉他
// 剩下的,就是按代码顺序正常在内存中插入这条数据进行保存
//如果这一条新闻之前没有保存过,findIndex返回值是-1,不走这个判断
// 会自动按正常代码流程保存
if(index>=0){
historyArr.splice(index, 1)
}
// 将值保存到item中
historyArr.unshift(item)
//用户浏览记录没有必要全部保存,只保存最近的10条数据就够了
historyArr=historyArr.splice(0,10)
uni.setStorageSync("historyArr", historyArr)
}
}
}
</script>
<style lang="scss">
.detail {
padding: 30rpx;
.title {
font-size: 46rpx;
color: #333;
}
.info {
background: #f6f6f6;
padding: 20rpx 20rpx;
font-size: 25rpx;
color: #666;
// 加盒模型,使作者和时间部分左右对齐
display: flex;
justify-content: space-between;
margin: 40rpx 0;
}
// 内容部分
.content {
padding-bottom: 50rpx;
[alt]{
max-width: 100%;
}
}
// 声明部分
.description {
background: #fef0f0;
font-size: 26rpx;
padding: 20rpx;
color: #f89898;
line-height: 1.8em;
}
}
</style>
优化:个人页面没有数据时不太好看,在user页面写一个提示文字样式:
再写一个盒子nohistory,装一个图片和暂时没有浏览记录的文字提示,然后要写一个判断,没有数据才让这个盒子显示出来,否则有没有数据他都会显示
<template>
<view class="user">
<view class="top">
<image src="../../static/images/history.png" mode=""></image>
<text>浏览历史</text>
</view>
<view class="content">
<view class="row" v-for="item in listArr">
<newsStyle :item="item" @click.native="goDetail(item)"></newsStyle>
</view>
</view>
<view class="nohistory" v-if="!listArr.length">
<image src="../../static/images/nohis.png" mode="widthFix"></image>
<view class="text">暂无浏览记录</view>
</view>
</view>
</template>
给盒子写一个css样式
.nohistory {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
image{
width: 400rpx;
}
.text {
font-size: 26rpx;
color: #888;
}
}