搜索结果searchResult
01 - 页面结构&样式
- 顶部的导航
- 给导航的左侧箭头添加一个点击事件(这个@click-left方法是vant组件中定义的):
<van-nav-bar left-arrow @click-left="onClickLeft" fixed title="搜索结果" />
- 在事件中应该回退到上一个页面
- 新闻数据的渲染
- 使用 list 组件来渲染数据
- 将首页中的结构复制过来,稍作修改
<!-- 上拉显示下面数据 --> <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad"> <div v-for="(item, index) in resultList" :key="index"> <!-- cell模板 --> <van-cell > <template #title> <h4>{{item.title}}</h4> <van-grid :border="false" v-if="item.cover.type !== 0" :column-num="3"> <van-grid-item v-for="(imgitem, imgindex) in item.cover.images" :key="imgindex"> <van-image lazy-load :src="imgitem" /> </van-grid-item> </van-grid> <div class="msgbox"> <span>{{item.aut_name}}</span> <span> {{item.comm_count}}评论</span> <!-- 过滤这个评论的时间 --> <span>{{item.pubdate}}</span> </div> </template> </van-cell> <van-grid direction="horizontal" :column-num="3"> <van-grid-item @click="comment" icon="comment-o" text="评论" /> <van-grid-item icon="like-o" text="点赞" /> <van-grid-item icon="exchange" text="分享" /> </van-grid> </div> </van-list>
注意点:
- 在
vue-router
有一个方法可以回退到上一个页面:this.$router.back()
02 - 得到关键字对应的文章数据
步骤:
- a. 在 mouted 中得到搜索的关键字
data () {
return {
loading: false,//上拉加载动画
finished: false,//是否完成
page: 1,//展示第几页
perpage: 10,//每页多少条
key: '',//从search页面路由传来的参数
resultList: []// 存放搜索结果文章数据的数组
}
},
mounted () {
// 接收search页面路由传来的参数,用key接收
this.key = this.$route.params.key
console.log(this.key)
},
- b. 在 list 组件的 onload 事件中发送请求到服务器得到关键字对应的文章数据
- 请求的服务器的接口:(获取搜索结果)
// 上拉加载
async onLoad () {
// 发送获得搜索结果的请求
const res = await apiGetResult({
page: this.page,
perpage: this.perpage,
key: this.key
})
// console.log(res)
// 每次发送请求获得的搜索结果数据要与上一次累加,而不是覆盖
this.resultList = res.data.data.results
- c. 直接将文章数据渲染到页面上
<div v-for="(item, index) in resultList" :key="index">
里面就是每个单元格的结构
</div>
样式结构:
03 - 完成上拉加载更多
步骤:
- 1.0 在 onload 中将 list 的组件的加载状态设置为 false
- 2.0 将得到的数据源进行接收,而不是覆盖
- 3.0 在 onload 中每次进行让 page 加 1
- 4.0 判断返回的结果是否为空
// 上拉加载
async onLoad () {
// 发送获得搜索结果的请求
const res = await apiGetResult({
page: this.page,
perpage: this.perpage,
key: this.key
})
// console.log(res)
// 每次发送请求获得的搜索结果数据要与上一次累加,而不是覆盖
this.resultList = [...this.resultList, ...res.data.data.results]
// 不要有搜索状态
this.loading = false
// 一次请求只展示10条数据,每发送一下就page加1,继续展示后面的数据
this.page++
// 判断如果没有返回的数据要显示'没有更多了'
if (res.data.data.results.length === 0) {
this.finished = true
}
},
comment () {
// 判断有没有登录
if (this.$store.state.userInfo.token) {
console.log('可以评论')
} else {
this.$toast.fail('对不起,还未登录,请登录!')
// 没有登录就去登录页面
this.$router.push('/login')
}
}
详细代码:
searchResult搜索结果页面,searshResult文件夹下的index.vue组件
<template>
<!-- 这个就是我们之前传参的方式?key=key -->
<!-- <div>搜索结果页面 ,参数为{{$route.query.key}}</div> -->
<!-- 这个是动态传递参数:当有多个参数时 -->
<!-- <div>搜索结果页面 ,参数为{{$route.params.key}},{{$route.params.key2}}</div> -->
<!-- <div>搜索结果页面 ,参数为{{$route.params.key}}</div> -->
<div class="result">
<van-nav-bar left-arrow @click-left="onClickLeft" fixed title="搜索结果" />
<!-- 上拉显示下面数据 -->
<van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<div v-for="(item, index) in resultList" :key="index">
<!-- cell模板 -->
<van-cell>
<template #title>
<!-- 标题 -->
<h4>{{item.title}}</h4>
<!-- 图片 -->
<van-grid :border="false" v-if="item.cover.type !== 0" :column-num="3">
<van-grid-item v-for="(imgitem, imgindex) in item.cover.images" :key="imgindex">
<van-image lazy-load :src="imgitem" />
</van-grid-item>
</van-grid>
<!-- 其他信息 -->
<div class="msgbox">
<span>{{item.aut_name}}</span>
<span> {{item.comm_count}}评论</span>
<!-- 过滤这个评论的时间 -->
<span>{{item.pubdate}}</span>
</div>
</template>
</van-cell>
<!-- 评论点赞分享 -->
<van-grid direction="horizontal" :column-num="3">
<van-grid-item @click="comment" icon="comment-o" text="评论" />
<van-grid-item @click="zan" icon="like-o" text="点赞" />
<van-grid-item icon="exchange" text="分享" />
</van-grid>
</div>
</van-list>
</div>
</template>
<script>
import { apiGetResult } from '@/api/other'
export default {
data () {
return {
loading: false,
finished: false,
page: 1, // 页数
perpage: 10, // 每页数量
key: '', // 搜索关键字
resultList: []// 存放搜索结果文章数据的数组
}
},
mounted () {
this.key = this.$route.params.key
},
methods: {
onClickLeft () {
// 返回上一个页面
this.$router.back()// 回到上一个路由中
},
// 上拉加载
async onLoad () {
// 发送获得搜索结果的请求
const res = await apiGetResult({
page: this.page,
perpage: this.perpage,
key: this.key
})
// console.log(res)
// 每次发送请求获得的搜索结果数据要与上一次累加,而不是覆盖
this.resultList = [...this.resultList, ...res.data.data.results]
// 不要有搜索状态
this.loading = false
// 一次请求只展示10条数据,每发送一下就page加1,继续展示后面的数据
this.page++
// 判断如果没有返回的数据要显示'没有更多了'
if (res.data.data.results.length === 0) {
this.finished = true
}
},
// 点击评论按钮时
// 不管点击评论还是点赞还是分享都要判断是否登录
// 如果每个方法都写很麻烦,可以把登录的判断封装成一个方法写在main.js中
comment () {
// 判断有没有登录
if (this.$store.state.userInfo.token) {
console.log('可以评论,处理后续逻辑')
} else {
this.$toast.fail('对不起,您还未登录,请登录!')
// 没有登录就去登录页面
this.$router.push('/checkLogin')
}
},
// 点赞时
// 利用自己封装的插件
zan () {
if (!this.$login()) {
return // 中止后面的代码
}
console.log('点赞,处理后续逻辑')
}
}
}
</script>
<style lang="less" scoped>
.result {
margin-top: 46px;
.van-nav-bar {
background-color: #3596fa;
/deep/ .van-nav-bar__title {
color: #fff;
}
}
/deep/ .van-icon-arrow-left{
color: #fff;
}
.msgbox{
span{
margin-right: 10px;
}
}
}
</style>
效果演示: