Vue3回到顶部(BackTop)

效果如下图:在线预览

在这里插入图片描述

APIs

参数说明类型默认值必传
bottomBackTop 距离页面底部的高度number | string40false
rightBackTop 距离页面右侧的宽度number | string40false
visibilityHeight滚动时触发显示回到顶部的高度number180false
toBackTop 渲染的容器节点 可选 元素标签名 例如 body 或者 元素本身,下同string | HTMLElement‘body’false
listenTo监听滚动的元素,如果为 undefined 会监听距离最近的一个可滚动的祖先节点string | HTMLElementundefinedfalse

Events

事件名称说明参数
show是否展现的回调(show: boolean) => void

创建回到顶部组件BackTop.vue

<script setup lang="ts">
import { ref, computed, watch, watchEffect, nextTick } from 'vue'
interface Props {bottom?: number|string // BackTop 距离页面底部的高度right?: number|string // BackTop 距离页面右侧的宽度visibilityHeight?: number // 滚动时触发显示回到顶部的高度to?: string|HTMLElement // BackTop 渲染的容器节点 可选 元素标签名(例如 'body') 或者 目标元素本身,下同listenTo?: string|HTMLElement // 监听滚动的元素,如果为 undefined 会监听距离最近的一个可滚动的祖先节点
}
const props = withDefaults(defineProps<Props>(), {bottom: 40,right: 40,visibilityHeight: 180,to: 'body',listenTo: undefined
})
const bottomPosition = computed(() => {if (typeof props.bottom === 'number') {return props.bottom + 'px'}return props.bottom
})
const rightPosition = computed(() => {if (typeof props.right === 'number') {return props.right + 'px'}return props.right
})
const backtop = ref()
const scrollTop = ref(0)
const scrollTarget = ref<any>()
watchEffect(() => {// 监听滚动的元素nextTick(() => {if (props.listenTo === undefined) {scrollTarget.value = getScrollParentElement(backtop.value?.parentElement)} else if (typeof props.listenTo === 'string') {scrollTarget.value = typeof document !== 'undefined' ? document.getElementsByTagName(props.listenTo)[0] : null} else if (props.listenTo instanceof HTMLElement) {scrollTarget.value = props.listenTo}if (scrollTarget.value) {observeElement(scrollTarget.value)scrollTarget.value.addEventListener('scroll', (e: any) => {scrollTop.value = e.target.scrollTop})}})
})
function observeElement (el: HTMLElement) {// 当观察到变动时执行的回调函数const callback = function (mutationsList: any, observer: any) {scrollTop.value = scrollTarget.value.scrollTop}// 观察器的配置(需要观察什么变动)const config = { attributes: true, subtree: true }// 创建一个观察器实例并传入回调函数const observer = new MutationObserver(callback)// 以上述配置开始观察目标节点observer.observe(el, config)
}
watchEffect(() => {// 渲染容器节点nextTick(() => {var target = nullif (typeof props.to === 'string') {target = typeof document !== 'undefined' ? document.getElementsByTagName(props.to)[0] : null} else if (props.to instanceof HTMLElement) {target = props.to}target && target.appendChild(backtop.value)})
})
const show = computed(() => {return scrollTop.value >= props.visibilityHeight
})
function getScrollParentElement (el: any) {if (el) {if (el.scrollHeight > el.clientHeight) {return el} else {return getScrollParentElement(el.parentElement)}}return null
}
const emits = defineEmits(['click', 'show'])
function onBackTop () {scrollTarget.value && scrollTarget.value.scrollTo({top: 0,behavior: 'smooth' // 平滑滚动并产生过渡效果})emits('click')
}
watch(show, (to) => {emits('show', to)
})
</script>
<template><Transition><div ref="backtop" v-show="show" @click="onBackTop" class="m-backtop" :style="`bottom: ${bottomPosition}; right: ${rightPosition};`"><slot><span class="m-icon"><svg class="u-icon" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xlinkHref="http://www.w3.org/1999/xlink"><g stroke="none" stroke-width="1" fill-rule="evenodd"><g transform="translate(-139.000000, -4423.000000)" fill-rule="nonzero"><g transform="translate(120.000000, 4285.000000)"><g transform="translate(7.000000, 126.000000)"><g transform="translate(24.000000, 24.000000) scale(1, -1) translate(-24.000000, -24.000000) translate(12.000000, 12.000000)"><g transform="translate(4.000000, 2.000000)"><path d="M8,0 C8.51283584,0 8.93550716,0.38604019 8.99327227,0.883378875 L9,1 L9,10.584 L12.2928932,7.29289322 C12.6834175,6.90236893 13.3165825,6.90236893 13.7071068,7.29289322 C14.0675907,7.65337718 14.0953203,8.22060824 13.7902954,8.61289944 L13.7071068,8.70710678 L8.70710678,13.7071068 L8.62544899,13.7803112 L8.618,13.784 L8.59530661,13.8036654 L8.4840621,13.8753288 L8.37133602,13.9287745 L8.22929083,13.9735893 L8.14346259,13.9897165 L8.03324678,13.9994506 L7.9137692,13.9962979 L7.77070917,13.9735893 L7.6583843,13.9401293 L7.57677845,13.9063266 L7.47929125,13.8540045 L7.4048407,13.8036865 L7.38131006,13.7856883 C7.35030318,13.7612383 7.32077858,13.7349921 7.29289322,13.7071068 L2.29289322,8.70710678 L2.20970461,8.61289944 C1.90467972,8.22060824 1.93240926,7.65337718 2.29289322,7.29289322 C2.65337718,6.93240926 3.22060824,6.90467972 3.61289944,7.20970461 L3.70710678,7.29289322 L7,10.585 L7,1 L7.00672773,0.883378875 C7.06449284,0.38604019 7.48716416,0 8,0 Z"></path><path d="M14.9333333,15.9994506 C15.5224371,15.9994506 16,16.4471659 16,16.9994506 C16,17.5122865 15.5882238,17.9349578 15.0577292,17.9927229 L14.9333333,17.9994506 L1.06666667,17.9994506 C0.477562934,17.9994506 0,17.5517354 0,16.9994506 C0,16.4866148 0.411776203,16.0639435 0.9422708,16.0061783 L1.06666667,15.9994506 L14.9333333,15.9994506 Z"></path></g></g></g></g></g></g></svg></span></slot></div></Transition>
</template>
<style lang="less" scoped>
.v-enter-from,
.v-leave-to {opacity: 0;transform: scale(.75);
}
.m-backtop {position: fixed;cursor: pointer;display: flex;align-items: center;justify-content: center;color: rgba(0, 0, 0, .88);border-radius: 22px;height: 44px;min-width: 44px;box-shadow: 0 2px 8px 0px rgba(0, 0, 0, .12);background-color: #fff;transition: all .3s cubic-bezier(.4, 0, .2, 1);&:hover {color: @themeColor;box-shadow: 0 2px 8px 3px rgba(0, 0, 0, .12);.m-icon .u-icon {fill: @themeColor;}}.m-icon {font-size: 26px;transition: color .3s cubic-bezier(.4, 0, .2, 1);height: 1em;width: 1em;line-height: 1em;text-align: center;display: inline-block;position: relative;fill: currentColor;transform: translateZ(0);.u-icon {fill: rgba(0, 0, 0, .88);pointer-events: none;height: 1em;width: 1em;}}
}
</style>

在要使用的页面引入

<script setup lang="ts">
import BackTop from './BackTop.vue'
import { ref } from 'vue'
function onShow (show: boolean) {console.log('show', show)
}
const scrollContainer = ref()
</script>
<template><div><h1>BackTop 回到顶部</h1><h2 class="mt30 mb10" style="margin-top: 150vh;">基本使用</h2><h3 class="mb10">BackTop 会找到首个可滚动的祖先元素并且监听它的滚动事件</h3><BackTop :right="100" @show="onShow" /><h2 class="mt30 mb10">自定义可视高度</h2><h3 class="mb10">自定义滚动时触发显示回到顶部的高度</h3><BackTop :bottom="100" :visibility-height="300"><div style="width: 200px; height: 40px; line-height: 40px; text-align: center; font-size: 14px;">可视高度:300px</div></BackTop><h2 class="mt30 mb10">自定义位置</h2><BackTop :right="40" :bottom="160"><div style="width: 200px; height: 40px; line-height: 40px; text-align: center; font-size: 14px;">改变位置</div></BackTop><h2 class="mt30 mb10">自定义监听目标</h2><h3 class="mb10">自定义设定监听哪个元素来触发 BackTop</h3><BackTop :listen-to="scrollContainer" :bottom="220" :visibility-height="10"><div style="width: 200px; height: 40px; line-height: 40px; text-align: center; font-size: 14px;">指定目标</div></BackTop><div ref="scrollContainer" style="overflow: auto; height: 72px; line-height: 1.5">这块应该写一个有意思的笑话。<br>这块应该写一个有意思的笑话。<br>这块应该写一个有意思的笑话。<br>这块应该写一个有意思的笑话。<br>这块应该写一个有意思的笑话。<br>这块应该写一个有意思的笑话。<br>这块应该写一个有意思的笑话。<br></div></div>
</template>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/98565.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Springboot启动异常 Command line is too long

Springboot启动异常 Command line is too long Springboot启动时直接报异常 Command line is too long. Shorten command line for xxxxxApplication or also for Spring Boot default解决方案: 修改 SystemApplication 的 Shorten command line&#xff0c;选择 JAR manife…

unity tolua热更新框架教程(2)

Lua启动流程 增加脚本luamain&#xff0c;继承luaclient 建立第一个场景GameMain&#xff0c;在对象GameMain挂载脚本LuaMain&#xff0c;启动场景 看到打印&#xff0c;lua被成功加载 lua入口及调用堆栈 这里会执行main.lua文件的main函数 C#接口导出 在此处配置C#导出的代码 …

【综述+3D】基于NeRF的三维视觉2023年度进展报告(截止2023.06.10)

论文&#xff1a;2003.Representing Scenes as Neural Radiance Fields for View Synthesis 官方网站&#xff1a;https://www.matthewtancik.com/nerf 突破性后续改进&#xff1a; Instant Neural Graphics Primitives with a Multiresolution Hash Encoding | 展示官网&#…

【Vuex状态管理】Vuex的基本使用;核心概念State、Getters、Mutations、Actions、Modules的基本使用

目录 1_应用状态管理1.1_状态管理1.2_复杂的状态管理1.3_Vuex的状态管理 2_Vuex的基本使用2.1_安装2.2_创建Store2.3_组件中使用store 3_核心概念State3.1_单一状态树3.2_组件获取状态3.3_在setup中使用mapState 4_核心概念Getters4.1_getters的基本使用4.2_getters第二个参数4…

vue3哪个数组方法在vue2上做了升级处理

在 Vue 3 中&#xff0c;v-for 指令的数组更新行为进行了升级处理。在 Vue 2 中&#xff0c;当使用 v-for 渲染数组时&#xff0c;如果对数组进行了以下操作&#xff0c;Vue 无法检测到变化&#xff1a; 直接通过索引修改数组元素&#xff0c;例如 arr[0] newValue修改数组的…

一文读懂GPU显卡的10个重要参数

在当今的高性能计算机世界中&#xff0c;GPU显卡的性能至关重要。这一领域的快速发展&#xff0c;使得图形渲染、游戏体验、视频编辑等高性能计算任务变得更加高效和流畅。正因如此&#xff0c;选择一款合适的GPU显卡变得越来越重要。在挑选GPU显卡时&#xff0c;了解其关键参数…

【SpringSecurity】十一、SpringSecurity集成JWT实现token的方法与校验

文章目录 1、依赖与配置2、JWT工具类3、认证成功处理器4、创建JWT过滤器5、安全配置类 1、依赖与配置 添加JWT的maven依赖&#xff1a; <!-- 添加jwt的依赖 --> <dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId…

vue 使用qrcode生成二维码并可下载保存

安装qrcode npm install qrcode --save代码 <template><div style"display: flex; flex-direction: column; align-items: center; justify-content center;"><div>查看溯源码&#xff0c;<a id"saveLink" style"text-decorati…

C#,《小白学程序》第十四课:随机数(Random)第一,几种随机数的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十四课&#xff1a;随机数&#xff08;Random&#xff09;第一&#xff0c;几种随机数的计算方法与代码 /// 本课初步接触一下随机数。 /// </summary> /// <param name"sender"></param> ///…

开发前期准备工作

开发前期准备工作 文章目录 开发前期准备工作0 代码规范0.1 强制0.2 推荐0.3 参考dao&#xff1a;跟数据库打交道service&#xff1a;业务层&#xff0c;人类思维解决controller&#xff1a;抽象化 0.4 注释规范0.5 日志规范0.6 专有名词0.7 控制层统一异常统一结构体控制层提示…

【git】从一个git仓库迁移到另外一个git仓库

在远端服务器创建一个新的仓库 用界面创建&#xff0c;当然也可以用命令创建 拉去源仓库 git clone --bare git192.168.10.10:java/common.gitgit clone --bare <旧仓库地址>拉去成功以后会出现 进入到文件夹内部 出现下面信息&#xff1a; 推送到新的远端仓库 git …

Java23种设计模式之【单例模式】

目录 一.单例模式的起源&#xff0c;和应用场景 1.单例模式的前世今生&#xff01; 2.什么是单例模式&#xff1f; 2.1使用单例模式的注意事项 2.2如何理解单例模式&#xff1f; 2.3单例模式的优势以及不足&#xff01; 2.4使用场景 二.实现 1.实现思路 1.1创建一个 S…