Vue中如何全局使用滚动到顶/底部按钮减少重复代码
可行实现方案
完全可以把重复代码统一收口,不需要每个页面单独编写,推荐两种落地方式,按需选择即可:
方案1:公共布局统一承载(改动最小,最推荐)
你现有的Default.vue本身就是布局组件,直接把它作为所有业务页面的公共父布局,所有相关逻辑只在布局里写一次即可:
- 保留布局里原有的
hasScroll状态、hasVerticalScroll滚动判断方法、路由监听、v-scroll指令、<ScrollToTop />组件声明 - 在
v-app标签内部加上路由出口<router-view />,路由配置里把所有需要滚动按钮的页面都作为这个布局的子路由,或者直接全局套用这个布局
调整后的布局模板核心代码:
<template> <v-app dark v-scroll="hasVerticalScroll"> <!-- 所有业务页面都会渲染在这里 --> <router-view /> <ScrollToTop v-if="hasScroll"/> </v-app> </template>
配置完成后,所有套用这个布局的页面会自动带上滚动按钮,单个页面不需要写任何和滚动按钮相关的代码。
方案2:组件内部内聚所有逻辑(彻底解耦,灵活度最高)
如果项目不方便统一调整布局,直接把外层的滚动条存在判断逻辑全部移到ScrollToTop.vue组件内部,让组件自己控制显隐、自己绑定事件,外层只需要在根组件放一次组件即可全局生效。
改造后的ScrollToTop.vue完整代码:
<template> <div v-if="hasScroll" v-scroll="onScroll" > <v-btn v-if = "!isVisible" fab fixed bottom right color="primary" @click="toBottom" > <v-icon>mdi-arrow-down-bold-box-outline</v-icon> </v-btn> <v-btn v-else fab fixed bottom right color="primary" @click="toTop"> <v-icon>mdi-arrow-up-bold-box-outline</v-icon> </v-btn> </div> </template> <script> export default{ data () { return { isVisible: false, position: 0, hasScroll: false } }, mounted() { // 初始化判断页面是否有纵向滚动条 this.checkHasVerticalScroll() // 监听窗口尺寸变化、路由跳转,重新判断滚动条状态 window.addEventListener('resize', this.checkHasVerticalScroll) this.$watch('$route', this.checkHasVerticalScroll) }, beforeUnmount() { // 移除事件监听避免内存泄漏 window.removeEventListener('resize', this.checkHasVerticalScroll) }, methods: { checkHasVerticalScroll() { this.hasScroll = document.body.offsetHeight > window.innerHeight }, onScroll () { this.isVisible = window.pageYOffset > 50 }, toTop () { this.position = window.pageYOffset window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) }, toBottom(){ this.position = this.position > 0 ? this.position : document.body.scrollHeight window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }) }, } } </script>
改完之后只需要做两步:
- 在Vue入口文件全局注册
ScrollToTop组件 - 在项目根组件
App.vue里写一次<ScrollToTop />
之后整个应用所有页面都自动生效,不需要任何单个页面单独定义状态、绑定方法、声明组件。
灵活控制小技巧
如果个别特殊页面不需要显示滚动按钮,可以在对应路由的meta配置里加标记,比如meta: { hideScrollBtn: true },在组件的checkHasVerticalScroll方法里读取当前路由的meta字段,匹配到隐藏标记时把hasScroll设为false即可,不需要额外改页面逻辑。
内容的提问来源于stack exchange,提问作者Gavin Teo Juen
相关产品推荐
相关产品推荐

