Allen's blog Allen's blog
首页
面经
算法 (opens new window)
分类

Allen

前端CV工程师
首页
面经
算法 (opens new window)
分类
  • Javascript

  • TypeScript

  • CSS

  • Vue

  • React

  • 框架和构建工具

  • 工具库

  • 常见业务场景

    • 事件委托
    • 滚动条闪动解决方案
    • 列表拖拽排序
    • linear-gradient背景渐变色
    • 表格组件数据加载,排序等
    • 时间业务
    • 滚动加载
      • 业务场景
      • 封装一个自定义指令
        • 逻辑
        • 代码
        • 积累知识点
    • 文件下载
  • Bug

  • 项目实战

  • 前端
  • 常见业务场景
Allen
2023-02-07
目录

滚动加载

https://juejin.cn/post/6844903961862897672

# 业务场景

在编写帖子(例如百度贴吧、微博、知乎等)的时候,用户往往从上往下浏览,当浏览到底部时,需要加载新的数据。

滚动加载和分页是两种常见的解决方案,分页较为简单,而有些场景下,使用滚动加载更加合适。

# 封装一个自定义指令

因为项目里需要用到的滚动加载的地方比较多,因此封装为一个指令,在使用起来更加方便

# 逻辑

  1. 自定义指令接收一个对象作为参数,

    {
      container: '.content-wp', // CSS Selector 滚动的容器
      callback: ()=>{}, // 回调函数,可以请求数据
      scrollBottom: number // 距离底部请求数据的阈值
    }
    
    1
    2
    3
    4
    5
  2. 监听滚动的容器的 scroll 事件 为什么是 scroll 而不是 wheel

    • wheel 事件先触发,scroll 后触发
    • 只要鼠标滚轮在滚动,wheel 事件就会触发,而 scroll 事件在滚动条到底部或者顶部后,就不会触发
    • 鼠标按住拖动滚动条时,wheel 事件不会触发(这里无法做到滚动条接近底部的时候请求新的数据)
  3. 使用节流函数,获取滚动条到底部的距离,如果到达阈值,就调用回调

  4. 当组件销毁的时候,移除监听,避免浪费性能

# 代码

import type { DirectiveBinding } from 'vue'

/**  传递的值为一个对象
 *{
 *    container: '.content-wp', // CSS Selector 滚动的容器
 *    callback: ()=>{}, // 回调函数,可以请求数据
 *    scrollBottom: number // 距离底部请求数据的阈值
 *}
 */

let scrollFn: any
export default {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
        const dom = document.querySelector(binding.value.container)
        // 监听容器
        dom.addEventListener(
            'scroll',
            (scrollFn = useThrottleFn(() => {
                // 节流函数
                //vue中获取滚动条到底部的距离
                const scrollBottom =
                    el.getBoundingClientRect().bottom - window.innerHeight
                // 设置阈值,当小于阈值时,调用回调
                if (scrollBottom < (binding.value.scrollBottom || 1400)) {
                    binding.value.callback()
                }
            }, 300))
        )
    },
    beforeUnmount(el: HTMLElement, binding: DirectiveBinding) {
        const dom = document.querySelector(binding.value.container)
        dom.removeEventListener('scroll', scrollFn)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 积累知识点

  1. Element 类型和 HTMLElement 类型不一样,Element 范围大得多 Element 是一个通用性非常强的基类,所有 Document 对象下的对象都继承自它。这个接口描述了所有相同种类的元素所普遍具有的方法和属性。一些接口继承自 Element 并且增加了一些额外功能的接口描述了具体的行为。例如, HTMLElement 接口是所有 HTML 元素的基本接口,而 SVGElement 接口是所有 SVG 元素的基础。大多数功能是在这个类的更深层级(hierarchy)的接口中被进一步制定的。

在 ts 中,通过 document.getElementById()返回 HTMLElement 类型,而 document.querySelect()返回 Element 类型。

  1. 节流函数不要自己写,使用最佳实践,避免一些错误,或者性能问题 useThrottleFn 来自 vueuse 工具,在官网 (opens new window)上可以看到使用说明,也可以配置自动导入 (opens new window)。
上次更新: 2023/12/16, 09:22:46
时间业务
文件下载

← 时间业务 文件下载→

最近更新
01
rollup使用配置文件rollup.config.ts打包
12-08
02
package.json导出类型
12-08
03
关键问题方案
11-17
更多文章>
Theme by Vdoing | Copyright © 2023-2023 Allen | Github
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式