当前位置: 首页 > news >正文

vue3写nav滚动事件中悬停在顶部

1. 防抖类Animate, 使用requestAnimationFrame代替setTimeout

也可以使用节流函数, lodash有现成的防抖和节流方法

_.debounce防抖

_.throttle节流

export default class Animate {constructor() {this.timer = null;}start = (fn) => {if (!fn) {throw new Error('需要执行函数');}if (this.timer) {this.stop();}this.timer = requestAnimationFrame(fn);};stop = () => {if (!this.timer) {return;}cancelAnimationFrame(this.timer);this.timer = null;};
}

2. 使用animate封装滚动方法

const animate = new Animate();

throttleScroll = e => animate.start(() => handleScroll(e));

3. 着手写滚动函数handleScroll

//滚动的函数
function handleScroll(e) {
  const scrollingElement = e.target.scrollingElement;
  const headerOffsetTop = header1.value.offsetTop; //header的高度
  const headerOffsetHeight = header1.value.offsetHeight;
  const scrollTop = scrollingElement.scrollTop;

  // 如果滚动元素的scrollTop比header元素的高度+offsetTop还大, 就让nav部分悬停在顶部!!!
  if (scrollTop >= headerOffsetHeight + headerOffsetTop) {
    isFixed.value = true;
  } else {
    isFixed.value = false;
  }
}

nav的定位何时设置为fixed的原理:

当滚动后, header元素因为向上滚动,或者向下滚动而消失不见时, 就让nav悬停在顶部, 反之就让nav元素正常显示在header元素下面

实践可知:

1) 滚动元素的scrollTop === header元素的offsetTop + header元素的offsetHeight时, header元素开始消失在视野;

2) scrollTop > header元素的offsetTop + header元素的offsetHeight时, header元素继续消失在视野;

3) 反之header就是可见到它的一部分就是它的全部都在视野范围中

4. 在onMounted钩子监听scroll事件(因为dom已经渲染完成)

onMounted(() => {
  nextTick(() => {
    window.addEventListener('scroll', throttleScroll, false);
  });

  throttleScroll = e => animate.start(() => handleScroll(e));
});

5. 组件将要销毁或者将要离开此组件时解除scroll事件绑定

onBeforeUnmount(() => { // 页面即将销毁取消事件监听(相当于vue2的beforeDestroy)
  //离开页面需要remove这个监听器,不然还是卡到爆。
  window.removeEventListener('scroll', throttleScroll);
});

<template><div class="fixed-top-container"><header class="header" :ref="header1">头部</header><nav class="fixed-top-nav" :ref="nav1" :class="{ isFixed }"><div class="box" v-for="(item, index) in navData" :key="index">{{ item.title }}</div></nav><ul class="fixed-top-list"><li class="list-item" v-for="(item, index) in listData" :key="index">{{ item }}</li></ul></div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, onBeforeUnmount, onDeactivated, nextTick, Ref } from 'vue'
import _ from 'lodash';
import Animate from '../../utils/animate'const navData = reactive([{ title: 'nav1', id: 1 },{ title: 'nav2', id: 2 },{ title: 'nav3', id: 3 },{ title: 'nav4', id: 4 },
]);const listData = reactive(Array.from({ length: 50 }, (_, i) => i + 1));const isFixed = ref(false); //是否固定的
let throttleScroll: any = null; //定义一个截流函数的变量
const header1 = ref('header1') as Ref;
const nav1 = ref('nav1') as Ref;
const animate = new Animate()//滚动的函数
function handleScroll(e) {const scrollingElement = e.target.scrollingElement;const headerOffsetTop = header1.value.offsetTop; //header的高度const headerOffsetHeight = header1.value.offsetHeight;const scrollTop = scrollingElement.scrollTop;// 如果滚动元素的scrollTop比header元素的高度+offsetTop还大, 就让nav部分悬停在顶部!!!if (scrollTop >= headerOffsetHeight + headerOffsetTop) {isFixed.value = true;} else {isFixed.value = false;}
}onMounted(() => {nextTick(() => {window.addEventListener('scroll', throttleScroll, false);});throttleScroll = e => animate.start(() => handleScroll(e));
});onBeforeUnmount(() => { // 页面即将销毁取消事件监听//离开页面需要remove这个监听器,不然还是卡到爆。window.removeEventListener('scroll', throttleScroll);
});
</script>
<style scoped lang="scss">
* {margin: 0;padding: 0;
}
.fixed-top-container {height: 100vh;& .header {height: 200px;width: 100%;background-color: #f40;}& .fixed-top-nav {display: flex;width: 100%;background-color: #f90;&.isFixed {position: fixed;left: 0;top: 0;z-index: 999;}& .box {font-size: 14px;height: 30px;line-height: 30px;color: #333;flex: 1 1 0%;}}& .fixed-top-list {list-style: none;& .list-item {width: 100%;height: 40px;line-height: 40px;font-size: 16px;border-bottom: 1px solid #333;background-color: #fff;}}
}
</style>

http://www.lryc.cn/news/215283.html

相关文章:

  • 关于qiling->UC_ERR_FETCH_UNMAPPED等执行EXE时内存错误的问题
  • 语言模型和人类的推理都依赖内容
  • 5.1 运输层协议概述
  • Jmeter保存csv数据文件出现乱码
  • 双闭环直流电机调速系统设计
  • [ poi-表格导出 ] java.lang.NoClassDefFoundError: org/apache/poi/POIXMLTypeLoader
  • 基于FPGA的图像差分运算及目标提取实现,包含testbench和MATLAB辅助验证程序
  • 闭环思维笔记
  • JMeter如何开展性能测试
  • 使用logback按天生成日志并按等级进行分类
  • 【Linux】Linux项目部署及更改访问端口号和jdk、tomcat、MySQL环境搭建的配置安装
  • Pytorch 注意力机制解析与代码实现
  • Python上下文管理:with语句执行原理
  • Mac-Java开发环境安装(JDK和Maven)
  • mac下的vscode配置编译环境
  • 洗衣洗鞋柜洗衣洗鞋小程序
  • vi vim 末尾编辑按GA 在最后一行下方新增一行编辑按Go
  • LeetCode热题100 240.搜索二维矩阵||
  • Anaconda安装及使用教程
  • 动态规划算法实现------转换(编辑、变换)问题
  • C#使用Oracle.ManagedDataAccess.dll
  • 分享88个工作总结PPT,总有一款适合您
  • 【华为OD题库-002】最佳植树距离-Java
  • 【python与数据结构】(leetcode算法预备知识)
  • 前端+Python实现Live2D虚拟直播姬
  • 华纳云 宝塔怎么配置香港服务器多ip?
  • 云计算是什么
  • 【POI-EXCEL-下拉框】POI导出excel下拉框数据太多导致下拉框不显示BUG修复
  • 【ES专题】ElasticSearch 高级查询语法Query DSL实战
  • 陕西某小型水库雨水情测报及大坝安全监测项目案例