You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 setup语法下滚动控制按钮v-if显隐失效问题排查

关联模板代码
<div class="app__land-bottom" v-if="isVisible">
  <a href="#projects">
    <img ref="arrowRef" id="arrow" src="./../assets/down.png" alt srcset />
  </a>
</div>
问题根因

代码不生效是两个问题叠加导致的,核心问题是响应式变量操作错误:

    1. ref响应式变量赋值方式错误:Vue3 <script setup> 中通过ref()创建的响应式变量是包装对象,在脚本逻辑中修改值必须操作其.value属性。原代码直接给isVisible赋值布尔值,相当于覆盖了ref对象的引用,完全丢失响应性,模板始终只能拿到初始值false,因此按钮一直隐藏。
    1. 事件监听绑定/移除的函数引用不一致:原代码在添加和移除scroll监听时都传入了新写的匿名箭头函数,两个函数内存地址完全不同,移除监听时无法匹配到之前绑定的回调,会造成内存泄漏,虽然不是本次显隐失效的直接原因,但属于必须修复的逻辑问题。
修复方案

按照以下三点调整即可:

  • 所有对ref变量的赋值操作,都通过.value属性完成
  • 将scroll事件的回调抽为固定引用的独立函数,保证绑定和移除时传入的是同一个函数
  • 组件挂载后主动执行一次显隐判断逻辑,避免首屏未触发滚动事件时状态错误

修复后的完整代码如下:

<script setup>
import { ref, onMounted, onUnmounted } from "vue";

const isVisible = ref(false);

const hideArrow = () => {
  const currentScroll = window.pageYOffset;
  // 脚本中修改ref值必须操作.value,逻辑可简化为直接赋值判断结果
  isVisible.value = currentScroll < 100;
}

onMounted(() => {
  window.addEventListener("scroll", hideArrow);
  hideArrow(); // 初始化时主动执行一次,保证首屏状态正确
});

onUnmounted(() => {
  // 传入和绑定时完全一致的函数引用,才能正确移除监听
  window.removeEventListener("scroll", hideArrow);
});
</script>

补充说明:Vue2中data返回的属性会被挂载到组件实例this上,直接通过this.xxx赋值即可触发响应式更新;Vue3的ref是独立的响应式包装类型,仅在模板中使用时会被自动解包,脚本逻辑中必须显式访问.value才能正确读写值。

内容的提问来源于stack exchange,提问作者user15392697

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 14:45:36