在Vue.js中使用Lenis时,点击菜单项为何跳转而非平滑滚动?
解决Vue.js中Lenis平滑滚动点击菜单直接跳转的问题
问题描述
在Vue.js项目中使用Lenis库实现平滑滚动,但点击导航菜单项时,页面直接跳转至目标区域,而非执行Lenis的平滑滚动逻辑。HTML环境下通过CDN引入Lenis时功能正常,但Vue项目内无法复现该效果。
问题根源
- Lenis实例作用域限制:App.vue中创建的
lenis是onMounted函数的局部变量,Header组件的原生onclick无法访问到该实例,导致Lenis的平滑滚动逻辑未触发,反而执行了a标签的默认锚点跳转。 - a标签默认行为未阻止:即使Lenis调用成功,a标签的原生跳转行为会直接覆盖平滑滚动效果,必须手动阻止。
修复方案
步骤1:让Header组件能访问到Lenis实例
方式1:全局暴露Lenis实例(快速解决)
修改App.vue的onMounted钩子,将Lenis实例挂载到window对象:
<script setup> import { onMounted } from "vue"; import Lenis from "@studio-freight/lenis"; // 导入其他组件... onMounted(() => { const lenis = new Lenis(); // 暴露到全局,让Header组件能访问 window.lenis = lenis; function raf(time) { lenis.raf(time); requestAnimationFrame(raf); } requestAnimationFrame(raf); }); </script>
方式2:使用Vue Provide/Inject传递实例(更优雅)
避免全局变量污染,用Vue的依赖传递机制:
- 在App.vue中提供实例:
<script setup> import { onMounted, provide } from "vue"; import Lenis from "@studio-freight/lenis"; // 导入其他组件... onMounted(() => { const lenis = new Lenis(); // 提供给子组件 provide('lenis', lenis); function raf(time) { lenis.raf(time); requestAnimationFrame(raf); } requestAnimationFrame(raf); }); </script>
- 在Header组件中注入并使用:
<script setup> import { ref, inject } from "vue"; const isActive = ref(false); const lenis = inject('lenis'); function deactive() { isActive.value = false; } // 封装滚动方法 const scrollToSection = (target) => { lenis?.scrollTo(target); } </script>
步骤2:阻止a标签的默认跳转行为
替换原生onclick为Vue事件处理,同时阻止默认行为:
针对全局暴露的实例:
<!-- 桌面端导航 --> <nav class="hidden w-1/3 items-center justify-end gap-6 bg-gradient-to-r from-fuchsia-400 to-pink-600 bg-clip-text text-lg font-semibold text-transparent lg:flex"> <a href="#stack" @click.prevent="window.lenis.scrollTo('#stack')">Stack</a> <a href="#projects" @click.prevent="window.lenis.scrollTo('#projects')">Projects</a> <a href="#contact" @click.prevent="window.lenis.scrollTo('#contact')"> Let's Talk </a> </nav> <!-- 移动端菜单示例 --> <a @click="deactive; window.lenis.scrollTo('#stack')" href="#stack" @click.prevent class="group relative h-full w-full" > <!-- 其余移动端a标签同理修改 -->
针对Provide/Inject的方式:
<!-- 桌面端导航 --> <nav class="hidden w-1/3 items-center justify-end gap-6 bg-gradient-to-r from-fuchsia-400 to-pink-600 bg-clip-text text-lg font-semibold text-transparent lg:flex"> <a href="#stack" @click.prevent="scrollToSection('#stack')">Stack</a> <a href="#projects" @click.prevent="scrollToSection('#projects')">Projects</a> <a href="#contact" @click.prevent="scrollToSection('#contact')"> Let's Talk </a> </nav> <!-- 移动端菜单示例 --> <a @click="deactive; scrollToSection('#stack')" href="#stack" @click.prevent class="group relative h-full w-full" > <!-- 其余移动端a标签同理修改 -->
内容的提问来源于stack exchange,提问作者qnyx
相关产品推荐
相关产品推荐

