IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 简易分页展示 -> 正文阅读

[JavaScript知识库]简易分页展示

效果

在这里插入图片描述

node后端代码

对网易音乐接口请求到的数据进行进一步处理

const express = require('express')
const axios = require('axios')
const cors = require('cors')
const app = express()
const port = 8001
app.use(cors())

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.get('/getSearchRes', (req, res) => {
  // console.log(req);
  const params = req.query

  axios.get('http://47.103.29.206:3000/search', { params }).then((response) => {
    // console.log(response);
    // console.log(response.data.result.songs);
    const data = response.data.result
    // console.log(data);
    if (data.songCount === 0) {
      res.json({
        code: 200,
        songs: [],
        hasMore: false,
        songCount: 0,
      })
    } else {
      const songs = response.data.result.songs
      // 三元运算符 到最后是没有歌曲的 map会报错
      const handleSongs =songs? songs.map((item) => {
        // console.log(item.artists);
        return {
          id: item.id,
          songName: item.name,
          // singer:item.artists  一个对象,里面有一个及以上数组,每一个数组是一个歌手
          singer: item.artists.map((list) => {
            return list.name
          }).join('/')  //数组合并
        }
      }):[]
      res.json({
        code: 200,
        songs: handleSongs,
        hasMore: data.hasMore,
        songCount: data.songCount,
      })
    }
  })
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}/getSearchRes`)
})

必选参数 : keywords : 关键词

可选参数 : limit : 返回数量 , 默认为 30 offset : 偏移数量,用于分页 , 如 : 如 😦 页数 -1)*30, 其中 30 为 limit 的值 , 默认为 0

有数据时
在这里插入图片描述
没有数据时
在这里插入图片描述

前端代码

通常,分页查询后端接收前端的字段有时是offset有时是page
用offset的话,每次可以用songs.length当做offset的值
page的话就比较简单了,直接传页数就行

这里传入的offset,这里前端传参数的时候可以用page*limit来代替 ,到时候触底加载只需让page++就能请求到下一页数据 page初始值为0
在这里插入图片描述
我觉得这个接口有点问题,offset为100 limit为100 那请求到的数据应该是第100-200首歌,一共有224首,所以hasmore应该是true才对,这里为什么是false

但是有的情况又是正常的比如说 搜索呵呵呵呵呵哈 limit为30

基础代码

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js"></script>
  <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>

<body>
  <div id="hello-vue" class="demo">
    <input v-model="inputData" type="text" />
    <ul class="songContainer">
      <li v-for="(item, index) in songs" :key="index">
        {{item.songName}}--{{item.singer}}
      </li>
    </ul>
    <button @click="page++" v-if="hasMore">点我page+1</button>
    <div v-if="!hasMore&&inputData">已经加载完了</div>
  </div>
  <script>
    const HelloVueApp = {
      data() {
        return {
          inputData: '',
          songs: [],
          hasMore: true,
          songCount: 0,
          // offset: 0,
          limit: 100,
          page: 0
        }
      },
      computed: {

      },
      created() {
        // 防抖
        this.$watch('inputData', this.debounce(async (val) => {
          this.initSearch()
          this.inputData = val
          const data =  await this.searchFun()
          this.songs = data.songs,
          this.hasMore = data.hasMore
        }))
      },

      watch: {
        // page变化的时候 请求下一页
        //async page(val) {
          // 请求到数据后拼接到songs后面
        // const data = await this.searchFun()
          //this.songs = this.songs.concat(data.songs)
          //this.hasMore = data.hasMore
        //},
       // hasMore(val) {
       //   if(!val){
        //    console.log("到最底部了");
        //  }
        }
      },
      methods: {
        // 防抖函数
        debounce(fn, delay = 300) {
          let timer = null
          return function () {
            if (timer) {
              clearTimeout(timer)
            }
            timer = setTimeout(() => {
              fn.apply(this, arguments)
              timer = null
            }, delay)
          }
        },
        // 每次搜索page songs之类的信息需要清除 
        initSearch() {
          this.songs = [],
            this.hasMore = true,
            this.songCount = 0,
            this.offset = 0,
            this.page = 0
        },
        // 向后端发送请求方法,返回请求到的数据
        async searchFun() {
          const result = await axios.get('http://localhost:8001/getSearchRes',
            {
              params: {
                keywords: this.inputData,
                limit: this.limit,
                offset: this.page * this.limit
              }
            })
          console.log(result);
          return result.data
        }

      },

    }
    Vue.createApp(HelloVueApp).mount('#hello-vue')
  </script>
</body>

</html>

better-scroll pullup使用

安装
cnpm i better-scroll -S
官网
https://better-scroll.github.io/docs/zh-CN/plugins/pullup.html
https://better-scroll.github.io/docs/zh-CN/plugins/observe-dom.html#%E5%AE%89%E8%A3%85

引入betterscroll并注册pullUpload
注意监听dom变化
在这里插入图片描述

初始化Betterscroll需要一个ref容器,这个容器在这里不能是ul节点 因为里面有很多子元素,外面再套个父盒子 ref名称叫rootRef
在这里插入图片描述

实例化BScroll 并传入配置参数
在这里插入图片描述

this.bs.on('pullingUp', this.pullingUpHandler) //监听pullingUp事件,进入回调函数

回调函数
每次一触底就显示一个loading的gif ,显示与否需要通过自定义一个标志变量控制–isPullUpLoad
当请求到数据以后,再将它变成false

请求下一页数据

在这里插入图片描述
loading与“已经加载完成显示”
在这里插入图片描述

扩展

如果有一些后端数据过滤掉了,比如说收费歌曲不展示,可能会导致请求到的数据是不满一屏的,这种情况就不满足better-scroll的滚动条件了,因为内层高度小于外层容器高度,不能滚动的话就不能触发监听触底的函数了,虽然说新版本的better-scroll已经解决了这个问题,但是仅仅依赖better-scroll自身的处理用户体验不是很好
在这里插入图片描述

比如说这个,它是不满一屏的,虽然上拉依然能够加载数据,但是用户不知道这种情况下还有更多数据,也就不会做上拉加载这种事情了。

看这个更直观的场景, songs为空,但是hasmore为true ,这种情况还是能拖动,并且有数据,而且每一屏的数据非常少,大量的数据都被过滤了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
现在来模拟一下这个场景, 让每一页能整除2和3的过滤掉
在这里插入图片描述

如何处理呢
希望数据不满一屏的情况下,再去请求下一页数据,直到填充到满足一屏为止,

bs(BScroll实例对象)内的maxScrollY属性
在这里插入图片描述
在这里插入图片描述

https://blog.csdn.net/qq_40196738/article/details/90200439
better-scroll的maxScrollY属性 并不是列表的offsetHeight,而是整体list高度减去当前显示区域??,即scroll还能滑动的偏移。还有this.scroll.y表示当前滑动偏移。

当第一次发起请求后,并且当maxScrollY>=-1 ,说明是不可滚动的,这种情况就不断去执行searchFn请求并拼接数据
并且在searchFn中继续判断是否>=-1 ;还有个要注意的就是nexttick ,数据到dom变化需要时间,等dom渲染之后再进行-1的判断

在这里插入图片描述
在这里插入图片描述

自动请求了三次
在这里插入图片描述

总代码

node

const express = require('express')
const axios = require('axios')
const cors = require('cors')
const app = express()
const port = 8001
app.use(cors())

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.get('/getSearchRes', (req, res) => {
  // console.log(req);
  const params = req.query

  axios.get('http://47.103.29.206:3000/search', { params }).then((response) => {
    // console.log(response);
    // console.log(response.data.result.songs);
    const data = response.data.result
    // console.log(data);
    if (data.songCount === 0) {
      res.json({
        code: 200,
        songs: [],
        hasMore: false,
        songCount: 0,
      })
    } else {
      const songs = response.data.result.songs
      // 三元运算符 到最后是没有歌曲的 map会报错
      const handleSongs =songs? songs.map((item) => {
        // console.log(item.artists);
        return {
          id: item.id,
          songName: item.name,
          // singer:item.artists  一个对象,里面有一个及以上数组,每一个数组是一个歌手
          singer: item.artists.map((list) => {
            return list.name
          }).join('/')  //数组合并
        }
      }):[]
      res.json({
        code: 200,
        songs: handleSongs.filter((item,index,arr)=>{
          if(!(index%2==0||index%3==0)){
            return item
          } 
        }),
        hasMore: data.hasMore,
        songCount: data.songCount
      })
    }
  })
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}/getSearchRes`)
})
<!--  -->
<template>
  <div id="hello-vue" class="demo">
    <input
      v-model="inputData"
      type="text"
      style="display: block; margin: 0 auto"
    />
    <div ref="rootRef" class="scrollCon" style="margin-top: 20px">
      <ul class="songContainer">
        <li v-for="(item, index) in songs" :key="index" style="font-size: 8px">
          {{ item.songName }}--{{ item.singer }}
        </li>
        <div style="width: 100%; padding-bottom: 20px" v-show="isPullUpLoad">
          <img
            src="https://img-blog.csdnimg.cn/fc901b1ca5974221b33e0d4b60eb64d2.gif"
            style="margin: 0 auto; display: block"
            width="30"
            height="30"
          />
        </div>
        <div v-if="!hasMore && inputData">--------已经加载完了--------</div>
      </ul>
    </div>
  </div>
</template>

<script>
import axios from "axios";
import BScroll from "better-scroll";
import { PullUpLoad } from "better-scroll";
import { ObserveDom } from "better-scroll";
BScroll.use(PullUpLoad);
BScroll.use(ObserveDom);
export default {
  data() {
    return {
      inputData: "ff",
      songs: [],
      hasMore: true,
      songCount: 0,
      // offset: 0,
      limit: 30,
      page: 0,
      isPullUpLoad: false,
      bs: null,
    };
  },
  computed: {},
  created() {
    // 防抖
    this.$watch(
      "inputData",
      this.debounce(async (val) => {
        this.initSearch();
        this.inputData = val;
        const data = await this.searchFun();
        this.songs = data.songs;
        this.hasMore = data.hasMore;
        await this.$nextTick()
        this.makeItScrollable()
      }),
      // watch api第三个参数   将立即以表达式的当前值触发回调
      {
        immediate: true,
      }
    );
  },
  mounted() {
    const bscroll = (this.bs = new BScroll(this.$refs.rootRef, {
      pullUpLoad: true,
      observeDOM: true,
      click: true,
    }));
    bscroll.on("pullingUp", this.pullingUpHandler);
  },
  watch: {
    hasMore(val) {
      if (!val) {
        console.log("到最底部了");
      }
    },
  },
  methods: {
    // 防抖函数
    debounce(fn, delay = 300) {
      let timer = null;
      return function () {
        if (timer) {
          clearTimeout(timer);
        }
        timer = setTimeout(() => {
          fn.apply(this, arguments);
          timer = null;
        }, delay);
      };
    },
    // 每次搜索page songs之类的信息需要清除
    initSearch() {
      (this.songs = []),
        (this.hasMore = true),
        (this.songCount = 0),
        (this.offset = 0),
        (this.page = 0);
    },
    // 向后端发送请求方法,返回请求到的数据
    async searchFun() {
      const result = await axios.get("http://localhost:8001/getSearchRes", {
        params: {
          keywords: this.inputData,
          limit: this.limit,
          offset: this.page * this.limit,
        },
      });
      console.log(result);

      return result.data;
    },
    // 触底回调
    async pullingUpHandler() {
      this.isPullUpLoad = true;
      console.log(12345);
      this.page++;
      // 请求到数据后拼接到songs后面
      const data = await this.searchFun();
      this.songs = this.songs.concat(data.songs);
      this.hasMore = data.hasMore;
      this.bs.finishPullUp();
      this.bs.refresh();
      this.isPullUpLoad = false;
  
    },
    // 不满一屏优化
    async makeItScrollable() {
      console.log(this.bs.maxScrollY);
      if (this.bs.maxScrollY >= -1) {
        this.page++
        const data = await this.searchFun();
        this.songs = this.songs.concat(data.songs);
        this.hasMore = data.hasMore;
      }
    },
  },
};
</script>
<style >
.scrollCon {
  height: 300px;
  overflow: hidden;
  padding-bottom: 30px;
}
</style>

还有一个地方需要修改的,就是如果input框里的值是空的,发送请求可以不用做请求直接return,就不用请求空数据了


其他链接 https://www.cnblogs.com/xzc666/p/9455861.html
iscroll

外链生成
请添加图片描述

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-08 13:54:34  更:2022-01-08 13:57:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:03:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码