【前端】Vue项目:旅游App-(16)home+hooks:窗口滚动到底部动态加载新数据、抽取到hook

2023-10-27

本项目博客总结:【前端】Vue项目:旅游App-博客总结

目标

监听窗口的滚动,滚动到底部则动态地加载houseList数据。
在这里插入图片描述

过程与代码

监听窗口的滚动

首先要监听窗口的滚动。

注意,滚动有两种:窗口滚动和页面滚动,关于如何区分它们:【前端】如何判断是页面滚动还是窗口滚动

window.addEventListener('scroll', () => {
    // 当前位置到顶部的距离
    const scrollTop = document.documentElement.scrollTop
    // 屏幕的长度
    const clientHeight = document.documentElement.clientHeight
    // 页面总体长度
    const scrollHeight = document.documentElement.scrollHeight

    // 滚动到底部:提前一点刷新
    if (scrollHeight <= scrollTop + clientHeight + 1) {
        homeStore.fetchHouseList()
        console.log('滚动到底部')
    }
})

效果:滚动到底部后就加载出了新的数据。

在这里插入图片描述

窗口上事件监听的移除

写到这里我们要进行一些思考:滚动到底部就加载数据 这一事件是绑定到整个App的窗口上的,但我们只需要它在home页面上绑定。

当我们切换到其他页面,如favor页面时,我们需要remove这个事件。也就是说,我们在写这个代码的时候要考虑到生命周期

生命周期选项 | Vue.js (vuejs.org)

生命周期钩子 | Vue.js (vuejs.org)

unmounted时移除此事件:

const scrollBottomListener = () => {
    // 当前位置到顶部的距离
    const scrollTop = document.documentElement.scrollTop
    // 屏幕的长度
    const clientHeight = document.documentElement.clientHeight
    // 页面总体长度
    const scrollHeight = document.documentElement.scrollHeight

    // 滚动到底部:提前一点刷新
    if (scrollHeight <= scrollTop + clientHeight + 1) {
        homeStore.fetchHouseList()
        console.log('滚动到底部')
    }
}

window.addEventListener('scroll', scrollBottomListener)

onUnmounted(() => {
    window.removeEventListener('scroll', scrollBottomListener)
})

那么自然会想到我们只在mounted时添加此事件的监听。

onMounted(() => {
    window.addEventListener('scroll', scrollBottomListener)
})

封装到一个hook

写到这里我们会发现,并不是只有home页面需要有监听滚动到底部的功能,别的页面也可能需要。因此,我们可以把这个功能抽取出来。

useScoll.js:

// 关于滚动到底部的代码逻辑
import { onMounted, onUnmounted } from "@vue/runtime-core";

export default function useScroll() {

    const scrollBottomListener = () => {
        // 当前位置到顶部的距离
        const scrollTop = document.documentElement.scrollTop
        // 屏幕的长度
        const clientHeight = document.documentElement.clientHeight
        // 页面总体长度
        const scrollHeight = document.documentElement.scrollHeight

        // 滚动到底部:提前一点刷新
        if (scrollHeight <= scrollTop + clientHeight + 1) {
            homeStore.fetchHouseList()
            console.log('滚动到底部')
        }
    }

    onMounted(() => {
        window.addEventListener('scroll', scrollBottomListener)
    })

    onUnmounted(() => {
        window.removeEventListener('scroll', scrollBottomListener)
    })
}

接下来我们只需要在 需要用到监听滚动到底部 这一功能的地方调用 这一函数即可。

这里,我们在home页面需要调用此函数,当判定滚动到底部后需要进行的操作是:动态加载更多的houselist。

接下来将讲两种实现这个功能的方法(名字随便取的):

  • 回调函数法
  • 返回值法

回调函数法(不推荐)

回调函数法,就是在useScoll中传入一个回调函数,来让滚动到底部时调用callback。这样我们就可以每次传入不同的callback来实现不同的功能。

useScroll.js:滚到底部时调用callback

// 关于滚动到底部的代码逻辑
import { onMounted, onUnmounted } from "@vue/runtime-core";

export default function useScroll(callback) {

    const scrollBottomListener = () => {
        // 当前位置到顶部的距离
        const scrollTop = document.documentElement.scrollTop
        // 屏幕的长度
        const clientHeight = document.documentElement.clientHeight
        // 页面总体长度
        const scrollHeight = document.documentElement.scrollHeight

        // 滚动到底部:提前一点刷新
        if (scrollHeight <= scrollTop + clientHeight + 1) {
            console.log('滚动到底部')
            if (callback) callback()
        }
    }

    onMounted(() => {
        window.addEventListener('scroll', scrollBottomListener)
    })

    onUnmounted(() => {
        window.removeEventListener('scroll', scrollBottomListener)
    })
}

home-content:

useScroll(() => {
    homeStore.fetchHouseList()
})

效果:可以实现。

但是这个方法有弊端

  • 回调函数不好管理
  • 不同功能可能需要传入不同数量的回调函数

总而言之,可以实现,但不推荐。

返回值法(推荐)

既然传入一个回调函数并不方便,那么我们可不可以让hook传出一个值,我们根据这个值在对应页面中实现各自的功能?答案是可以的。

useScroll.js:

// 关于滚动到底部的代码逻辑
import { onMounted, onUnmounted } from "@vue/runtime-core";
import { ref } from 'vue'

export default function useScroll() {
    // 初始默认为没有到底
    const isReachBottom = ref(false)

    const scrollBottomListener = () => {
        // 当前位置到顶部的距离
        const scrollTop = document.documentElement.scrollTop
        // 屏幕的长度
        const clientHeight = document.documentElement.clientHeight
        // 页面总体长度
        const scrollHeight = document.documentElement.scrollHeight

        // 滚动到底部:提前一点刷新
        if (scrollHeight <= scrollTop + clientHeight + 1) {
            console.log('滚动到底部')
            isReachBottom.value = true
        }
    }

    onMounted(() => {
        window.addEventListener('scroll', scrollBottomListener)
    })

    onUnmounted(() => {
        window.removeEventListener('scroll', scrollBottomListener)
    })

    return { isReachBottom }
}

home-content:

这里我们用watch来监听数据的变化:Vue.js中 watch(深度监听)的最易懂的解释 - 星期九 - 博客园 (cnblogs.com)

const { isReachBottom } = useScroll()
watch(isReachBottom, (newValue) => {
    if (newValue) {
        homeStore.fetchHouseList()
        isReachBottom.value = false
    }
})

对于homeStore.fetchHouseList()更好的写法是:在它返回promise之后再修改isReachBottom的值:这样意味着它先加载了新数据,再使标记变为“没有到底”。

const { isReachBottom } = useScroll()
watch(isReachBottom, (newValue) => {
    if (newValue) {
        homeStore.fetchHouseList().then(() => {
            isReachBottom.value = false
        })
    }
})

效果

达成目标。

在这里插入图片描述

总代码

修改或添加的文件

在这里插入图片描述

hooks的useScroll

监听窗口滚动到底部的逻辑抽取到hooks。

// 关于滚动到底部的代码逻辑
import { onMounted, onUnmounted } from "@vue/runtime-core";
import { ref } from 'vue'

export default function useScroll() {
    // 初始默认为没有到底
    const isReachBottom = ref(false)

    const scrollBottomListener = () => {
        // 当前位置到顶部的距离
        const scrollTop = document.documentElement.scrollTop
        // 屏幕的长度
        const clientHeight = document.documentElement.clientHeight
        // 页面总体长度
        const scrollHeight = document.documentElement.scrollHeight

        // 滚动到底部:提前一点刷新
        if (scrollHeight <= scrollTop + clientHeight + 1) {
            console.log('滚动到底部')
            isReachBottom.value = true
        }
    }

    onMounted(() => {
        window.addEventListener('scroll', scrollBottomListener)
    })

    onUnmounted(() => {
        window.removeEventListener('scroll', scrollBottomListener)
    })

    return { isReachBottom }
}

home-content

调用hooks。

<template>
    <div class="content">
        <h2>热门精选</h2>

        <div class="list">
            <template v-for="(item, index) in houseList" :key="item.data.houseId">
                <houseItemV9 v-if="item.discoveryContentType === 9" :item="item.data"></houseItemV9>
                <houseItemV3 v-else-if="item.discoveryContentType === 3" :item="item.data"></houseItemV3>
            </template>
        </div>
    </div>
</template>

<script setup>
import { storeToRefs } from "pinia";
import useHomeStore from "../../../store/modules/home";
import houseItemV9 from "../../../components/house-item/house-item-v9.vue";
import houseItemV3 from "../../../components/house-item/house-item-v3.vue";
import useScroll from '@/hooks/useScroll.js'
import { watch } from 'vue'

const homeStore = useHomeStore()
homeStore.fetchHouseList()
const { houseList } = storeToRefs(homeStore)
// console.log(houseList)

const { isReachBottom } = useScroll()
watch(isReachBottom, (newValue) => {
    if (newValue) {
        homeStore.fetchHouseList().then(() => {
            isReachBottom.value = false
        })
    }
})

</script>

<style lang="less" scoped>
.content {
    padding: 0 20px;

    h2 {
        font-size: 20px;
        font-weight: 700;
    }

    .list {
        margin-top: 20px;
        display: flex;
        flex-wrap: wrap;
    }
}
</style>

参考

Element.scrollTop - Web API 接口参考 | MDN (mozilla.org)

Element - Web API 接口参考 | MDN (mozilla.org)

【前端】如何判断是页面滚动还是窗口滚动_karshey的博客-CSDN博客

Vue.js中 watch(深度监听)的最易懂的解释 - 星期九 - 博客园 (cnblogs.com)

生命周期选项 | Vue.js (vuejs.org)

生命周期钩子 | Vue.js (vuejs.org)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【前端】Vue项目:旅游App-(16)home+hooks:窗口滚动到底部动态加载新数据、抽取到hook 的相关文章

随机推荐

  • 学会Python有哪些可以做的兼职?所有途径全在这里了...

    可以干的兼职有好多 主要围绕Python的应用方向来 自媒体 现在很多搞技术的都开始进入自媒体领域 比如微信公众号 知乎 B站 抖音 小红书等 这些平台上只要你有流量 你就可以通过广告 播放量 带货等方式赚钱 当然了 自媒体需要积累 如果能
  • 数模学习(模糊数学篇)——模糊识别(python实现)

    目录 一 储备知识 1 课本定义 2 通俗理解 引入小例 如何识别 二 模糊识别方法 1 最大隶属度原则 计算方法 使用方向 2 择近原则 择近度计算方法和使用方向 三 模糊识别例题 例题1 湖泊水质识别 1 指标库标准化和样品库标准化 2
  • python爬虫怎么学?浅谈python爬虫学习的10大步骤

    如今 做跨境电商与海外社媒的从业者可谓是越来越多了 若想采集海外的相关数据 基本上是离不开爬虫的 很多小白都是不太了解这一块内容的 并且网络爬虫基本上是要使用python语言的 所以这里我就来讲讲用python爬虫要怎么学 以及分为几个步骤
  • 4.mybatis 高级结果查询

    商品订单模型 一个用户可以下n个订单 一个订单只能属于一个用户 一个订单可以有多个订单详情 订单和订单详情是一对多的关系 一个订单中可以有多个商品 一个商品也可以属于多个订单 订单和商品多对多的关系 关联查询几个需要注意的细节 1 超过三个
  • 计算机管理中的用户和组里的名称和全名有什么不同

    用户名是登录使用的 全名就是一个注释 组决定了用户的权限 计算机上 System 组的权限最高 用户中 Administrators 组的权限最高 Users 组居中 Guests 组最低 根据权限的逐渐降低 用户可访问的文件 可更改的设置
  • JAVA项目:后台管理页面——显示数据库中所有信息+删除和编辑(MySQL)

    此DEMO包含以下功能 后台管理界面 删除 修改 显示数据库里所有数据 修改编辑界面 表格检验 修改数据库里的值 后台管理界面 头像为默认头像 视频暂未上传 backstageUI jsp
  • get传递数组参数

    get请求时传递的参数有一个是数组时 要做序列化处理 下面是不需要用插件就可以解决的方法 axios有一个方法 paramsSerializer 可以处理params的数组 下面举例 vue文件里请求时传的是三个参数 methods 发送请
  • MotionBuilder调整骨骼大小尺寸

    需要先选中骨骼太能调整尺寸大小
  • 交通事故致因分析

    1 挖掘背景 随着时代的发展 我们的出行变的越来越便利的同时 也带来的越发严重的交通安全事故 我国的经济高速发展 全国汽车保有量 交通道路 人口等都在不断的增加 同时道路交通安全事故也进入高发期 分析事故发生的原因 找到事故发生的内在规律
  • 幂等的这几个问题没有考虑到,你恐怕是在写Bug吧!

    免费视频福利推荐 2T免费学习视频 内含精选高频面试题 SSM Spring全家桶 微服务 MySQL MyCat 集群 分布式 高并发 中间件 Linux 网络 多线程 Jenkins Nexus Docker ELK等等免费学习视频 持
  • Python 操作MySql数据库(封装、优雅)

    Python 记录操作MySql数据库 封装 优雅 前言 封装代码 进行测试 结果展示 前言 学了pymysql第三方库 pip install pymysql 来操作MySql数据库后 浅记一下对MySql进行 关于我的MySql之优雅封
  • ValueError: shape mismatch: objects cannot be broadcast to a single shape 画条形图bar报错

    ValueError shape mismatch objects cannot be broadcast to a single shape plt bar x y 可能是条形图的x和y的数组长度不同造成的 需要修改数据 保持一致
  • 前端手机号码校验

    vue前端手机号码校验
  • zxing设置条码两边空白(EncodeHintType.MARGIN)无效的分析

    最新项目需要使用到zxing生成条码 条码格式为CODE128 CODE128的规则可参考 点击打开链接 当调用 MultiFormatWriter encode str BarcodeFormat CODE 128 mwidth mHei
  • 对CocosCreatorr的Draw call的理解

    Draw call比较直观的描述应该是 在CPU不改变渲染数据的情况下 openGL的一次渲染 opengGL的一次渲染 CPU调用图形绘制接口来使GPU执行渲染操作 渲染流程是CPU和GPU并行工作的过程 CPU和GPU之间通过一系列的缓
  • 小米便签开源项目本地环境搭建

    基于Android Studio 和Gradle 的小米便签配置和安装 一 Android Studio的中文社区 官网 下载最新的Android Studio 点击开始传送http www android studio org 可参考下文
  • 让异步的多个ajax顺序执行的方法

    就是说等第一个ajax传回来后再执行第二个ajax跟其他的js代码 ajax type POST url http xxx xxx aspx data success function msg 试了几次 除了在 那里 执行接下来的代码外 要
  • CSDN 编程竞赛第15期题解

    CSDN 编程竞赛第15期题解 1 求并集 由小到大输出两个单向有序链表的并集 如链表 A 1 gt 2 gt 5 gt 7 链表 B 3 gt 5 gt 7 gt 8 输出 1 gt 2 gt 3 gt 5 gt 7 gt 8 inclu
  • day01Git

    1 Git介绍 1 1版本控制 理解 无论是代码编写 还是文档编写 我们都会遇到对文档内容反复修改的情况 1 2开发中存在的问题 理解 程序员小明负责的模块就要完成了 就在即将提交发布之前的一瞬间 电脑突然蓝屏 硬盘光荣下岗 几个月来的努力
  • 【前端】Vue项目:旅游App-(16)home+hooks:窗口滚动到底部动态加载新数据、抽取到hook

    文章目录 目标 过程与代码 监听窗口的滚动 窗口上事件监听的移除 封装到一个hook 回调函数法 不推荐 返回值法 推荐 效果 总代码 修改或添加的文件 hooks的useScroll home content 参考 本项目博客总结 前端