vant list列表组件分页场景使用 及 搜索框输入-请求数据-防抖处理

需求:使用vant List列表组件实现页面分页加载,分页数据后端返回

template模版:

<van-list
  v-if="!noData"
  v-model:loading="loadingpage"
  :finished="finishedpage"
  finished-text="没有更多数据了"
  @load="onLoad"
>
   <div
       class="recommendItem"
       v-for="(item, index) in collectPositioninfoList"
       :key="index"
       @click="recommendItemClick(item.id)"
    >
  </div>
</van-list>

js分页写法

// 定义接口参数
const current = ref(1)
const size = 10
const total = ref(0)

// 定义分页相关数据
const loadingpage = ref(false)
const finishedpage = ref(false)

// 控制占位图显示
const noData = ref(false)

// 定义接口数据数组
const collectPositioninfoList = ref([])

//封装接口请求数据方法
const getList = async (obj) => {
  const {
    data,
    data: { records } //对数据 data 和列表数据 records 进行结构
  } = await collectPositioninfoApi(obj) //调用后端接口
  if (records.length == 0) {
    // 判断获取数据条数若等于0
    collectPositioninfoList.value = [] // 清空数组
    finishedpage.value = true // 停止加载
    noData.value = true // 展示占位图
  } else {
    noData.value = false //不展示占位图
  }
  // 若数据条数不等于0
  total.value = data.total // 给数据总条数赋值

  collectPositioninfoList.value.push(...records) // 将数据放入list中

  loadingpage.value = false // 加载状态结束

  // 如果list长度大于等于总数据条数,数据全部加载完成
  if (collectPositioninfoList.value.length >= total.value) {
    finishedpage.value = true // 结束加载状态
  }
}


// onLoad 方法页面首次加载会执行一次,组件滚动到底部触发load事件并将loading 设置成 true
const onLoad = () => {
  // 若加载条到了底部
  let timer = setTimeout(() => {
    // 定时器仅针对本地数据渲染动画效果,项目中axios请求不需要定时器
    let obj = {
      current: current.value,
      size: size,
      id: route.query.serial_no || '',
      category: route.query.category || '', //	岗位类别
      degree: contentEduItem.value || '', //学历
      position: searchValueKeyword.value || '' //岗位名称(模糊查询)
    }
    getList(obj) // 调用上面方法,请求数据
    current.value++ // 分页数加一
    finishedpage.value && clearTimeout(timer) //清除计时器
  }, 100)
}

要注意,对于分页的数据使用tab栏切换加载时,除了要清空数组数据进行数据的重加载,另外针对loading和finish的控制也要重新计算。

遇到了一个bug记录一下,tab切换完数据时下滑加载数据----会导致滚动条划至顶部,这里在加载数据之前对 loading.value = true 重新赋值就解决了


需求,实现搜索框输入内容 防抖处理(减少请求的次数)

  • 搜索输入时 ,判断用户在输入完成后 实现即时的自动搜索
  • 并且要防止过度自动搜索消耗性能

思路: 使用 watch + v-model

  • v-model 实现数据输入的同步更新(数据想想绑定)
  • watch 监听输入变化,使用防抖函数实现后续操作

template模版: 搜索组件

<van-search
  clearable
  v-model="searchValueKeyword"
  placeholder="搜索岗位名称"
  shape="round"
  show-action
  autocomplete="off"
>
  <template #action>
    <div @click="onZhiWeiBtn">职位</div>
  </template>
</van-search>

js防抖写法:在一定时间内多次触发只执行最后一次

// 定义搜索框数据
const searchValueKeyword = ref('')

// 因为 防抖函数定义 返回的是一个回调函数, 我们可以用一个变量来接收
const searchInput = debounce(1000)

// 使用watch 监听 搜索框数据 变化
watch(searchValueKeyword, () => {
  searchInput() //调用防抖的回调函数
})

// 防抖函数
function debounce(delay) {
  let timer //声明一个存储定时器的变量
  return function () {
    if (timer) clearTimeout(timer) // 再次触发时之前的定时器没有结束就清空定时器
    timer = setTimeout(() => {
      // 暂时理解不了(this,arguments)指向改变的问题
      // getList.call(this, arguments)

      current.value = 1
      collectPositioninfoList.value = []
      let obj = {
        current: 1,
        size: size,
        id: route.query.serial_no || '',
        category: route.query.category || '', //	岗位类别
        degree: contentEduItem.value, //学历
        position: searchValueKeyword.value //岗位名称(模糊查询)
      }
      getList(obj) //每隔一秒发送一次请求
      // 不输入延迟 则默认 1000 ms
    }, delay || 1000)
  }
}