黑马头条项目-day8-搜索模块-上拉功能、历史记录,联想搜索
2021/6/12 18:53:39
本文主要是介绍黑马头条项目-day8-搜索模块-上拉功能、历史记录,联想搜索,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
历史记录功能
目标:实现搜索历史记录功能
- 初始化历史记录数据
data () { return { // 搜索关键字 q: '', // 历史关键字 history: JSON.parse(localStorage.getItem('keywords') || '[]') } },
- 历史记录有数据才显示
<div class="history-box" v-else-if="history.length">
- 渲染历史数据
<van-cell v-for="(item, index) in history" :key="index"> <a class="word_btn">{{item}}</a> <van-icon @click="delHistory(key)" class="close_btn" slot="right-icon" name="cross"/> </van-cell>
总结:
- 回车后,缓存历史关键字
- 进入搜索组件,初始化数据时,直接读取缓存
- 动态渲染历史数据
- 数组去重操作
handleSearch () { // 回车触发后:1、保存历史关键字;2、跳转到搜索列表页面 this.history.unshift(this.q) // Set是ES6引入的一个构造函数,存储结构和数组类似,其中不允许放重复数据 this.history = [...new Set(this.history)] // 把history数组放入缓存 localStorage.setItem('keywords', JSON.stringify(this.history)) }
总结:基于ES6提供Set构造函数进行去重比较方便
注意:Set是ES6引入的一个构造函数,存储结构和数组类似,其中不允许放重复数据
- 删除历史
deleteSingle (index) { // 点击叉号删除对应的历史关键字 this.history.splice(index, 1) // 缓存也要更新 window.localStorage.setItem(SEARCHKEY, JSON.stringify(this.history)) },
- 清空历史
<van-icon name="delete" @click="deleteAll"></van-icon>
deleteAll () { // 清除所有的历史关键字 this.history = [] // 缓存也要清空 window.localStorage.removeItem('keywords') },
注意:删除时要删除两个部分:1、data中的数据;2、缓存中的数据
联想搜索功能
目标:实现联想搜索功能
- 封装搜索接口方法
export const searchList = (q) => { return request({ method: 'get', url: 'v1_0/suggestion', params: { q } }) }
<van-search @input='keywordList'
// 联想查询 async keywordList () { const ret = await searchList(this.q) this.keylist = ret.data.options },
总结:输入一次关键字,调用一次接口得到关键字匹配的列表数据。
- 实现函数防抖效果debounce/throttle(节流)
函数防抖的作用:限制任务执行的频率
如果连续两次触发条件的时间间隔超过规定的时间,那么才触发一次任务,如果两次触发条件的间隔小于这个固定时间,那么始终不触发任务。
触发条件:输入一个字符
规定的时间:1秒
任务:调用接口发送请求
// 联想查询 keywordList () { // 如下的写法就是函数防抖 clearTimeout(this.timer) if (!this.q.trim()) return this.timer = setTimeout(async () => { const ret = await searchList(this.q) this.keylist = ret.data.options }, 1000) },
总结:
- 函数防抖 debounce :连续两次触发条件超过特定时间才会执行一次任务。(关键字搜索、账号重复性验证)
- 函数节流 throttle:在固定的时间内,无论触发多少次条件,仅仅执行一次任务。(分页动态加载)
- 渲染搜索列表结果
<van-cell :key='index' v-for='(item, index) in keylist' icon="search"> <p v-html='item'></p> </van-cell>
注意:展示内容需要使用v-html指令
- 实现联想列表的高亮控制
// 需求:让列表项内容与关键自匹配后高亮(包裹一层span标签) this.keylist = ret.data.options.map(item => { // const arr = [] // const arr = new Array() // const obj = {} // const obj = new Object() // const reg = /\d/ // const reg = new RegExp('\d') // 原生js方法replace用于替换整个字符串中的子串 const reg = new RegExp(this.q, 'ig') return item.replace(reg, `<span>${this.q}</span>`) })
总结:熟悉基于正则表达式构造函数的用法,以及js的replace方法的用法。
- 路由跳转传递参数的另一种方式
总结:通过编程式导航跳转路由时,通过?方式将参数拼接到路由路径之后
this.$router.push('/sresult?kw=' + this.q) // 路由映射 { path: '/sresult', component: Sresult }
组件内部如何得到这个问号后的参数?this.$route.query.kw
this.$router.push('/sresult/' + this.q) // 路由映射 { path: '/sresult/:kw', component: Sresult }
组件内部获取这种路由参数的方式:this.$route.params.kw
- 实现搜索页面的跳转
- 回车后跳转,参数为输入的关键字
// 实现搜索 handleSearch () { // 防止输入空字符串 // q.trim()是原生js的方法,用于去掉两侧的空格 '' if (!this.q.trim()) return // 回车触发后:1、保存历史关键字;2、跳转到搜索列表页面 this.history.unshift(this.q) // Set是ES6引入的一个构造函数,存储结构和数组类似,其中不允许放重复数据 this.history = [...new Set(this.history)] // 把history数组放入缓存 window.localStorage.setItem('keywords', JSON.stringify(this.history)) // 跳转到搜索列表页面 // this.$router.push('/sresult?kw=' + this.q) // this.$router.push('/sresult/' + this.q) this.$router.push({ // path: 'sresult', name: 'myresult', query: { kw: this.q } }) }
总结:
- 编程式导航的跳转有多种用法
- 可以这路由映射中设置name属性,编程式导航可以基于name值跳转
- 不同的传参方式属性不同 query/params
- 点击联想的列表项跳转,参数为列表项内容
// 点击联想条目跳转 handleJump (kw) { // kw此时包括span高亮的标签,需要去掉 const reg = new RegExp(`<span>${this.q}</span>`, 'ig') kw = kw.replace(reg, this.q) this.$router.push({ name: 'myresult', query: { kw: kw } }) },
总结:点击跳转之前,传递的参数需要去掉span高亮标签。
搜索结果-基本布局
目标:实现搜索列表页面基本布局
- 搜索列表布局
<div class="container"> <!-- 导航固定定位 fixed --> <van-nav-bar fixed title="搜索结果" left-arrow @click-left="$router.back()" /> <!-- 文章列表 --> <van-list v-model="loading" :finished="finished" finished-text="没有更多了"> <van-cell-group> <van-cell> <div class="article_item"> <h3 class="van-ellipsis">PullRefresh下拉刷新PullRefresh下拉刷新下拉刷新下拉刷新</h3> <div class="img_box"> <van-image class="w33" fit="cover" src="https://img.yzcdn.cn/vant/cat.jpeg" /> <van-image class="w33" fit="cover" src="https://img.yzcdn.cn/vant/cat.jpeg" /> <van-image class="w33" fit="cover" src="https://img.yzcdn.cn/vant/cat.jpeg" /> </div> <div class="img_box"> <van-image class="w100" fit="cover" src="https://img.yzcdn.cn/vant/cat.jpeg" /> </div> <div class="info_box"> <span>你像一阵风</span> <span>8评论</span> <span>10分钟前</span> </div> </div> </van-cell> </van-cell-group> </van-list> </div>
- 搜索结果列表样式
.container { padding-top: 92px; height: 100%; overflow-y: auto; box-sizing: border-box; } .article_item { h3 { font-weight: normal; line-height: 2; } .img_box { display: flex; justify-content: space-between; .w33 { width: 33%; height: 180px; } .w100 { height: 360px; width: 100%; } } .info_box { color: #999; line-height: 2; position: relative; span { padding-right: 20px; } } }
搜索结果-上拉功能
目标:实现搜索上拉功能
- 封装上拉加载接口
// 根据关键字搜索文章列表 export const searchArticles = (options) => { return request({ method: 'get', url: 'v1_0/search', // axios传递get请求参数本来就是使用params params: { // 当前页码 page: options.pagenum, // 每页的条数 per_page: options.pagesize, // 查询的关键字 q: options.kw } }) }
- 列表相关数据
data () { return { loading: false, finished: false, // 搜索参数 queryData: { page: 1, perPage: 10, // 通过路由参数初始化数据 q: this.$route.query.q }, // 搜索结果 list: [], // 列表总数 total: 0 } }, methods: { async searchArticles () { // 根据关键字搜索文章列表结果 const [err, ret] = await searchArticles(this.queryData) if (err) { this.$toast.fail('查询文章失败') } else { // 获取文章的列表数据和总数 this.list = ret.data.results this.total = ret.data.total_count } } },
- 触发上拉加载更多动作
methods: { async onl oad () { // 页面加载时,触发一次,如果不够一屏,再次调用一次 const ret = await searchArticles(this.queryData) this.list.push(...ret.data.results) this.total = ret.data.total_count // 结束这次的加载 this.loading = false // 判断加载完成的状态 if (this.list.length >= this.total) { // 没有更多数据需要加载 this.finished = true } else { // 还有更多数据可以加载:页码累加 this.queryData.pagenum += 1 } } }, created () { // 获取路由参数中的查询关键字 this.queryData.kw = this.$route.query.kw }
- 渲染列表内容
<van-cell v-for='item in list' :key='item.art_id.toString()'> <div class="article_item"> <h3 class="van-ellipsis">{{item.title}}</h3> <div class="img_box"> <van-image :key='index' v-for='(img, index) in item.cover.images' :class="[{w33: item.cover.type===3}, {w100: item.cover.type===1}]" fit="cover" :src="img" /> </div> <div class="info_box"> <span>{{item.aut_name}}</span> <span>{{item.comm_count}}评论</span> <span>{{item.pubdate|formatTime}}</span> </div> </div> </van-cell>
总结:
- 基于pagenum和pagesize的分页逻辑
- van-list组件的基本使用
- 类名的动态绑定的用法
总结
- 缓存搜索的历史关键字:本地存储API
- 数组去重:基于ES6引入的新的构造函数Set
- 删除历史关键字:单个删除和全部删除(本地存储API)
- 防止输入空字符:原生js的trim方法的用法
- 函数防抖的业务流程(※);对比函数节流
- 概念;应用场景;代码实现
- 关键字匹配基本功能:调用接口;填充页面
- 列表项目的高亮控制:正则的构造函数用法(好处:支持变量)(※)
- 路由传递参数的用法(基于问号传递参数)(※)
- 编程式导航路由跳转,路由映射支持name,也可以用name跳转(※)
- 注意传递参数:query/params
- name的用法
- 基于pagenum和pagesize参数的分页:基于时间的分页
这篇关于黑马头条项目-day8-搜索模块-上拉功能、历史记录,联想搜索的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南