如何在Vue 3中使用Composition API实现滚动时隐藏导航栏
解决Vue3 Composition API实现滚动显示/隐藏导航栏的问题
原生JS实现代码:
let prevScrollpos = window.pageYOffset; window.onscroll = function () { console.log('scrolling') let currentScrollPos = window.pageYOffset; if (prevScrollpos > currentScrollPos) { // @ts-ignore document.getElementById("navbar").style.top = "0"; } else { // @ts-ignore document.getElementById("navbar").style.top = "-65px"; } prevScrollpos = currentScrollPos; }
下面提供三种适配Vue3 Composition API的解决方案:
一、在Navbar.vue组件内实现(推荐)
直接在导航组件内部监听滚动事件,结合Vue的响应式和生命周期钩子管理监听:
<template> <nav ref="navbarRef" class="navbar"> <!-- 导航内容 --> </nav> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue' const navbarRef = ref(null) let prevScrollpos = window.pageYOffset const handleScroll = () => { const currentScrollPos = window.pageYOffset if (navbarRef.value) { navbarRef.value.style.top = prevScrollpos > currentScrollPos ? '0' : '-65px' } prevScrollpos = currentScrollPos } onMounted(() => { window.addEventListener('scroll', handleScroll) }) onUnmounted(() => { window.removeEventListener('scroll', handleScroll) }) </script> <style scoped> .navbar { position: fixed; top: 0; left: 0; width: 100%; height: 65px; transition: top 0.3s ease; /* 加上过渡动画更流畅 */ } </style>
说明:
- 用
ref获取导航栏DOM元素,避免直接通过getElementById操作DOM,更符合Vue的规范 - 在
onMounted中注册滚动监听,onUnmounted中移除,防止内存泄漏 - 添加过渡动画让显示/隐藏更平滑
二、自定义指令方案
如果需要在多个组件复用该功能,可以封装成自定义指令:
1. 全局注册指令(main.js)
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.directive('scroll-navbar', { mounted(el) { let prevScrollpos = window.pageYOffset const handleScroll = () => { const currentScrollPos = window.pageYOffset el.style.top = prevScrollpos > currentScrollPos ? '0' : '-65px' prevScrollpos = currentScrollPos } window.addEventListener('scroll', handleScroll) // 监听组件卸载,移除事件监听 el._scrollHandler = handleScroll }, unmounted(el) { window.removeEventListener('scroll', el._scrollHandler) } }) app.mount('#app')
2. 在组件中使用
<template> <nav v-scroll-navbar class="navbar"> <!-- 导航内容 --> </nav> </template> <style scoped> .navbar { position: fixed; top: 0; left: 0; width: 100%; height: 65px; transition: top 0.3s ease; } </style>
三、在App.vue中全局监听
如果需要统一管理滚动逻辑,也可以在根组件中实现:
<template> <div id="app"> <nav ref="navbarRef" class="navbar"> <!-- 导航内容 --> </nav> <router-view /> </div> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue' const navbarRef = ref(null) let prevScrollpos = window.pageYOffset const handleScroll = () => { const currentScrollPos = window.pageYOffset if (navbarRef.value) { navbarRef.value.style.top = prevScrollpos > currentScrollPos ? '0' : '-65px' } prevScrollpos = currentScrollPos } onMounted(() => { window.addEventListener('scroll', handleScroll) }) onUnmounted(() => { window.removeEventListener('scroll', handleScroll) }) </script>
内容的提问来源于stack exchange,提问作者Bathrobespierre
相关产品推荐
相关产品推荐

