vue中记录页面的滚动距离

本文介绍两种方法实现在Vue.js应用中从pageOne页面跳转到pageTwo页面时记录并恢复滚动位置,同时根据来源决定是否刷新数据。一种方法是使用Vue的keep-alive组件缓存页面状态;另一种则通过路由元信息存储滚动位置。

业务需求:pageOne页面是一个商品列表页面,在这个页面点击商品,就会跳转到pageTwo商品详细页面。此时再从pageTwo页面返回到pageOne页面时,pageOne页面需要做到:1.记录pageOne之前的滚动的距离。2.不重新请求数据。而从其它页面进入到pageOne页面时,pageOne页面不需要记录之前的滚动距离和需要重新请求数据。

1.使用keep-alive组件的实现方法

App.vue

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/other">other</router-link> |
      <router-link to="/page-one">page-one</router-link> |
      <router-link to="/page-two">page-two</router-link>
    </div>
    <div class="container">
      <!-- 使用keep-alive是为了缓存page-one组件内部scroll的值 -->
      <keep-alive>
        <router-view/>
      </keep-alive>
    </div>
  </div>
</template>

page-one.vue

<template>
  <div class="page-one" ref="pageOneContainer">
    <p v-for="item in 20" :key="item">测试</p>
  </div>
</template>
<script>
export default {
  name: '',
  data () {
    return {
      scroll: 0
    }
  },
  beforeRouteEnter (to, from, next) {
    if (from.name === 'pageTwo') {
      next(vm => {
        const pageOneContainer = vm.$refs.pageOneContainer
        // 记录滚动高度
        pageOneContainer.scrollTop = vm.scroll
        // 不重新请求数据
        vm.notFetchData()
      })
    } else {
      next(vm => {
        const pageOneContainer = vm.$refs.pageOneContainer
        // 不记录滚动高度
        pageOneContainer.scrollTop = 0
        // 重新请求数据
        vm.fetchData()
      })
    }
  },
  beforeRouteLeave (to, from, next) {
    if (to.name === 'pageTwo') {
      const pageOneContainer = this.$refs.pageOneContainer
      this.scroll = pageOneContainer.scrollTop
    }
    next()
  },
  methods: {
    fetchData () {
      console.log('need flash')
    },
    notFetchData () {
      console.log('do not need flash')
    }
  }
}
</script>
<style scoped>
  .page-one {
    height: 100px;
    background-color: #ccc;
    overflow: auto;
  }
</style>

2.不使用keep-alive组件的实现方法

App.vue

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/other">other</router-link> |
      <router-link to="/page-one">page-one</router-link> |
      <router-link to="/page-two">page-two</router-link>
    </div>
    <div class="container">
      <router-view/>
    </div>
  </div>
</template>

page-one.vue

<template>
  <div class="page-one" ref="pageOneContainer">
    <p v-for="item in 20" :key="item">测试</p>
  </div>
</template>
<script>
export default {
  name: '',
  beforeRouteEnter (to, from, next) {
    if (from.name === 'pageTwo') {
      next(vm => {
        const pageOneContainer = vm.$refs.pageOneContainer
        // 记录滚动高度
        pageOneContainer.scrollTop = vm.$route.meta.scroll || 0 // 从page-one路由的meta属性中获取scroll
        // 不重新请求数据
        vm.notFetchData()
      })
    } else {
      next(vm => {
        const pageOneContainer = vm.$refs.pageOneContainer
        // 不记录滚动高度
        pageOneContainer.scrollTop = 0
        // 重新请求数据
        vm.fetchData()
      })
    }
  },
  beforeRouteLeave (to, from, next) {
    if (to.name === 'pageTwo') {
      const pageOneContainer = this.$refs.pageOneContainer
      // 将page-one页面的scroll记录到路由的meta中
      this.$route.meta.scroll = pageOneContainer.scrollTop
    }
    next()
  },
  methods: {
    fetchData () {
      console.log('need flash')
    },
    notFetchData () {
      console.log('do not need flash')
    }
  }
}
</script>
<style scoped>
  .page-one {
    height: 100px;
    background-color: #ccc;
    overflow: auto;
  }
</style>

 效果展示:

使用keep-alive缓存组件只是为了保存page-one组件中的scroll属性,若不想缓存组件,可以有很多钟方法来记录scroll,例如上面使用的路由元信息meta、vuex、cookie、sessionStorage、localStorage等都能实现同样的效果。

 

转载于:https://www.cnblogs.com/luyuefeng/p/11401260.html

<think> 首先,用户在询问在 Vue 3 中监听页面滚动并获取滚动距离和可视化区域大小的方法。我从用户的历史记录中看到了一些引用,这些引用是关于 Vue滚动事件的,包括 Vue 2 和 Vue 3 的一些例子。我需要基于这些提供准确的响应。 关键点: - 用户想要在 Vue 3 中实现。 - 监听页面滚动。 - 获取滚动距离(例如,scrollTop)。 - 获取当前可视化区域大小(例如,clientHeight 或 window.innerHeight)。 来自参考: - 引用 [1]:展示了如何在滚动时加载内容,使用 querySelector 获取元素,并检查 scrollTop, clientHeight, scrollHeight。 - 引用 [2]:这是一个 Vue 3 的例子,使用 window.addEventListener("scroll", handleScroll),获取 window.pageYOffset 和 window.innerHeight。 - 引用 [3]:展示了一个 Vue 组件,其中在 mounted 生命周期中添加滚动事件监听器,并在 beforeRouteLeave 中移除它,以避免内存泄漏。 系统指令: - 所有行内数学表达式必须使用 $...$。 - 独立公式使用 $$...$$。 - 语法正确。 - 使用中文回答。 - 生成相关问题。 - 在引用的段落末尾添加引用标识。 我的回答结构: 1. **介绍**:简要解释如何在 Vue 3 中实现滚动监听。 2. **实现方法**: - 使用 Composition API(因为用户在 Vue 3 中)。 - 在 setup() 或使用 onMounted 添加事件监听器。 - 在 onUnmounted 中移除监听器。 - 获取滚动距离:使用 window.scrollY 或 window.pageYOffset。 - 获取可视化区域大小:使用 window.innerHeight。 - 提供一个代码示例。 3. **添加引用**:基于用户提供的引用,自然地添加引用标识。 4. **生成相关问题**:在末尾列出几个相关问题。 代码示例: - 使用 Vue 3 的 Composition API。 - 在 onMounted 中添加事件监听器。 - 在 onUnmounted 中移除。 - 在事件处理函数中,获取 scrollY 和 innerHeight。 确保响应清晰、分步。 最终,生成相关问题: - 例如: 1. 如何在 Vue 3 中优化滚动性能? 2. 如何基于滚动位置触发动画? 3. Vue 3 中处理滚动事件的最佳实践是什么? 完整的响应: - 用中文写。 - 结构良好。 </think> ### Vue 3 中监听页面滚动并获取滚动距离与可视化区域大小的实现方法 在 Vue 3 中,监听页面滚动事件并获取滚动距离(如 `scrollY` 或 `pageYOffset`)和当前可视化区域大小(如 `window.innerHeight`)可以通过 Composition API 实现。核心步骤包括: 1. 在组件挂载时(`onMounted`)添加 `scroll` 事件监听器。 2. 在事件处理函数中访问 `window` 对象获取滚动距离和视口高度。 3. 在组件卸载时(`onUnmounted`)移除监听器,避免内存泄漏。 以下是完整示例代码和分步说明: ```vue <template> <div> <p>滚动距离: {{ scrollY }}px</p> <p>可视化区域高度: {{ innerHeight }}px</p> </div> </template> <script> import { ref, onMounted, onUnmounted } from 'vue'; export default { setup() { // 定义响应式变量存储滚动距离和可视区域高度 const scrollY = ref(0); const innerHeight = ref(window.innerHeight); // 滚动事件处理函数 const handleScroll = () => { scrollY.value = window.scrollY; // 或 window.pageYOffset(两者等价) innerHeight.value = window.innerHeight; }; // 组件挂载时添加监听 onMounted(() => { window.addEventListener('scroll', handleScroll); }); // 组件卸载时移除监听 onUnmounted(() => { window.removeEventListener('scroll', handleScroll); }); return { scrollY, innerHeight }; }, }; </script> ``` #### 关键点说明: 1. **获取滚动距离**: - 使用 `window.scrollY` 或 `window.pageYOffset`(两者在大多数浏览器中行为一致),表示页面在垂直方向滚动的像素值。例如,当用户向下滚动时,此值会增大[^2]。 2. **获取可视化区域大小**: - `window.innerHeight` 返回当前窗口的可视高度(单位为像素),包括滚动条但不包括浏览器界面元素(如地址栏)。这代表了用户可见区域的高度[^2]。 3. **事件监听与移除**: - 在 `onMounted` 生命周期钩子中添加 `scroll` 事件监听器,确保只在组件活跃时响应滚动。 - 在 `onUnmounted` 中移除监听器,防止组件销毁后事件累积导致性能问题或错误[^3]。 4. **响应式更新**: - 通过 `ref` 定义响应式变量(如 `scrollY` 和 `innerHeight`),当滚动发生时自动更新模板中的值。 #### 注意事项: - **性能优化**:如果滚动事件频繁触发,可加入防抖(debounce)或节流(throttle)函数减少开销。 - **元素级监听**:如需监听特定 DOM 元素的滚动(如容器),使用 `document.querySelector('.scrollWrap')` 获取元素对象,再访问其 `scrollTop` 和 `clientHeight` 属性[^1]。 - **兼容性**:`window.scrollY` 和 `window.pageYOffset` 在现代浏览器中均可用,Vue 3 的 Composition API 简化了状态管理[^2][^3]。 该方法广泛用于无限滚动加载、滚动触发动画或响应式布局场景中[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值