ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

黑马头条项目-day8-搜索模块-上拉功能、历史记录,联想搜索

2021-06-12 18:30:43  阅读:300  来源: 互联网

标签:const day8 关键字 kw 上拉 跳转 搜索 history


历史记录功能

目标:实现搜索历史记录功能

  • 初始化历史记录数据
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>

总结:

  1. 回车后,缓存历史关键字
  2. 进入搜索组件,初始化数据时,直接读取缓存
  3. 动态渲染历史数据
  • 数组去重操作
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)
},

总结:

  1. 函数防抖 debounce :连续两次触发条件超过特定时间才会执行一次任务。(关键字搜索、账号重复性验证)
  2. 函数节流 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
    }
  })
}

总结:

  1. 编程式导航的跳转有多种用法
  2. 可以这路由映射中设置name属性,编程式导航可以基于name值跳转
  3. 不同的传参方式属性不同 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>

总结:

  1. 基于pagenum和pagesize的分页逻辑
  2. van-list组件的基本使用
  3. 类名的动态绑定的用法

总结

  • 缓存搜索的历史关键字:本地存储API
  • 数组去重:基于ES6引入的新的构造函数Set
  • 删除历史关键字:单个删除和全部删除(本地存储API)
  • 防止输入空字符:原生js的trim方法的用法
  • 函数防抖的业务流程(※);对比函数节流
    • 概念;应用场景;代码实现
  • 关键字匹配基本功能:调用接口;填充页面
  • 列表项目的高亮控制:正则的构造函数用法(好处:支持变量)(※)
  • 路由传递参数的用法(基于问号传递参数)(※)
  • 编程式导航路由跳转,路由映射支持name,也可以用name跳转(※)
    • 注意传递参数:query/params
    • name的用法
  • 基于pagenum和pagesize参数的分页:基于时间的分页

标签:const,day8,关键字,kw,上拉,跳转,搜索,history
来源: https://blog.csdn.net/weixin_55537701/article/details/117853163

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有