如何在Vue 3 Composition API中实现滚动时导航栏类名的增删功能
Vue 3 Composition API 导航栏滚动类切换实现方案
实现核心逻辑
- 监听页面滚动事件,实时获取当前页面垂直滚动距离
- 设置滚动阈值,当滚动距离超过阈值时标记导航栏为滚动状态,回到阈值内时取消标记
- 动态绑定class到导航栏元素,根据状态自动添加/移除
scrolled类 - 添加节流逻辑优化滚动事件触发频率,避免性能损耗
- 组件卸载时移除滚动事件监听,防止内存泄漏
完整单文件组件实现示例
<template> <!-- 导航栏容器 --> <header :class="['site-navbar', isScrolled ? 'scrolled' : '']"> <div class="navbar-content"> <div class="logo">Graana Clone</div> <nav class="nav-menu"> <a href="#" v-for="item in navItems" :key="item">{{ item }}</a> </nav> </div> </header> <!-- 页面其他内容 --> <main class="page-content"> <!-- 填充足够内容使页面可滚动即可测试效果 --> </main> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue' // 响应式状态:标记导航栏是否处于滚动状态 const isScrolled = ref(false) // 滚动阈值,单位px,可根据设计需求调整 const SCROLL_THRESHOLD = 10 // 节流函数:控制滚动事件回调触发频率,默认200ms触发一次 const throttle = (func, delay = 200) => { let lastCall = 0 return (...args) => { const now = Date.now() if (now - lastCall >= delay) { lastCall = now func.apply(this, args) } } } // 滚动事件处理逻辑 const handleScroll = throttle(() => { const scrollY = window.scrollY || document.documentElement.scrollTop isScrolled.value = scrollY > SCROLL_THRESHOLD }) // 组件挂载时添加滚动监听 onMounted(() => { window.addEventListener('scroll', handleScroll, { passive: true }) }) // 组件卸载时移除滚动监听 onUnmounted(() => { window.removeEventListener('scroll', handleScroll) }) // 示例导航菜单数据 const navItems = ['Buy', 'Rent', 'Sell', 'Projects', 'Agents', 'Guides'] </script> <style scoped> .site-navbar { position: fixed; top: 0; left: 0; width: 100%; padding: 1.2rem 5%; transition: all 0.3s ease; z-index: 999; /* 默认未滚动状态样式 */ background-color: transparent; color: #fff; } /* 滚动后添加的样式 */ .site-navbar.scrolled { background-color: #fff; color: #1a1a1a; box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08); padding: 0.8rem 5%; } .navbar-content { display: flex; align-items: center; justify-content: space-between; max-width: 1400px; margin: 0 auto; } .nav-menu { display: flex; gap: 2rem; } .nav-menu a { text-decoration: none; color: inherit; font-weight: 500; } .page-content { margin-top: 80px; min-height: 200vh; /* 模拟长页面,方便测试滚动效果 */ } </style>
可调整参数说明
- 修改
SCROLL_THRESHOLD的值可调整触发scrolled类的滚动高度 - 修改节流函数的
delay参数可调整滚动事件响应灵敏度,数值越低响应越快,性能消耗也越高 - 样式部分可根据实际设计需求调整过渡效果、背景色、内边距等属性,和预期效果对齐
可选优化:抽离为可复用Composable
如果需要在多个组件复用滚动逻辑,可以把核心逻辑抽为自定义Hook:
// composables/useNavbarScroll.js import { ref, onMounted, onUnmounted } from 'vue' export function useNavbarScroll(threshold = 10, throttleDelay = 200) { const isScrolled = ref(false) const throttle = (func, delay) => { let lastCall = 0 return (...args) => { const now = Date.now() if (now - lastCall >= delay) { lastCall = now func.apply(this, args) } } } const handleScroll = throttle(() => { const scrollY = window.scrollY || document.documentElement.scrollTop isScrolled.value = scrollY > threshold }, throttleDelay) onMounted(() => { window.addEventListener('scroll', handleScroll, { passive: true }) }) onUnmounted(() => { window.removeEventListener('scroll', handleScroll) }) return { isScrolled } }
组件内直接引入使用即可:
import { useNavbarScroll } from '@/composables/useNavbarScroll' const { isScrolled } = useNavbarScroll(10, 150)
内容的提问来源于stack exchange,提问作者Waseem Abbas
相关产品推荐
相关产品推荐

