跳转页面 bscroll 无法无法从顶部滚动

在基于Vue开发的移动端应用中,遇到页面跳转后滚动位置不正确的问题。当从页面A滚动到一定位置后跳转到页面B,B页面会继承A页面的滚动位置。分析认为这可能由于Vue的keep-alive特性导致。为了解决这个问题,提出了在全局路由守卫中设置每次进入路由时重置窗口滚动位置的方案,即在beforeEach钩子中使用window.scroll(0,0)确保页面滚动始终从顶部开始。

项目场景:

基于Vue开发移动端页面,页面可滚动,从A页面条跳转到B页面,B页面滚动能从0开始

问题描述:

页面A沿Y轴滚动一段距离,然后跳转到页面B,在进入B页面时,B页面已经滚到页面A的距离,返回页面A,发现A还在之前的滚动位置;

原因分析:

可能是Vue页面有keep-alive缓存功能

解决方案:

在路由守卫回调中,设置每次进入路由时,将window的scroll值设置为0;window.scroll(0, 0);

// 全局路由守卫
router.beforeEach((to, from, next) => {
  window.scroll(0, 0);
  next()
})
实现左右菜单滚动联动,修复底部点击跳转问题。 1. 初始化better-scroll:在Category.vue中导入插件,初始化左右侧滚动实例。 1)安装插件better-scroll 插件,具体命令如下 yarn add @ /core@2.5 --save 2)导入better-scroll核心库,定义左侧(leftBscroll)和右侧(rightBscroll滚动实例变量。 import BScroll from " "; //导入better-scroll核心库 let leftBscroll = null //左侧滚动实例 let rightBscroll = null //右侧滚动实例 3)编写初始化滚动实例的函数。 左侧滚动:配置click: true(允许点击)和mouseWheel: true(支持鼠标滚轮)。 右侧滚动:除基础配置外,设置probeType: 3(实时监听滚动事件),并绑定scroll事件记录滚动距离(通过scrollY存储 Y 轴绝对值)。 const scrollY = ref(0) // 右侧列表滑动的 y 轴坐标 // 初始化 BScroll const initBScroll = () => { // 初始化左菜单 leftBscroll = new BScroll(" ", { //补全左侧容器类名 click: true, mouseWheel: true, }); // 初始化右菜单 rightBscroll = new BScroll(" ", { //补全右侧容器类名 click: true, mouseWheel: true, probeType: 3, // 实时派发 scroll 事件 }); // 监听右侧滚动,更新scrollY rightBscroll.on('scroll', pos => { scrollY.value = Math.abs(pos.y) }) }; 4)监听数据变化并重新初始化:当菜单数据(menus)更新后,通过watch监听,在nextTick中调用initBScroll(确保 DOM 更新后初始化)。 watch(menus, () => { nextTick(() => { initBScroll(); initRightHeight(); }); }); 2.实现滚动联动 1)单击左侧菜单项,右侧菜单滚动到相应位置 在clickList方法中,添加下面代码,实现左侧菜单项点击时(clickList),通过rightLiTops(右侧各分类项的顶部距离)获取目标位置,调用右侧滚动实例的scrollTo方法滚动到对应位置。 const clickList = (index) => { console.log(rightLiTops.value[index]); scrollY.value = rightLiTops.value[index]; rightBscroll. (0, -scrollY.value); //补全滚动方法 }; 单击左侧菜单的最后一项时,右侧菜单可以滚动到相应的位置,给出截图: 2)右侧菜单滚动,激活左侧菜单项 ①绑定左侧菜单项样式与ref:在左侧li标签中,通过:class绑定current激活样式(index === currentIndex时生效),并通过ref="menuList"绑定菜单项容器。 //在script中定义menuList const menuList = ref() //在template中修改左侧菜单项 <li class="menu-item" v-for="(menu, index) in menus" :key="index" @click="clickList(index)" :class="{ }" ref="menuList" > ②计算当前激活的左侧索引:通过computed定义currentIndex,根据scrollY判断右侧滚动位置所在的分类区间,返回对应左侧索引(最后一个分类特殊处理)。 import { onMounted, watch, nextTick, ref, computed } from 'vue' <script setup> ……(原有代码) const currentIndex = (() => { return rightLiTops.value.findIndex((top, index) => { if (index === rightLiTops.value.length - 2) { return true } if (scrollY.value >= top && scrollY.value < rightLiTops.value[index + 1]) { initLeftScroll(index) return true } }) }); </script> ③左侧滚动到激活项:编写initLeftScroll函数,通过menuList获取激活项元素,调用左侧滚动实例的scrollToElement方法将其滚动到可视区域。 const initLeftScroll = (index) => { const menu = menuList.value; let el = menu[index]; leftBscroll. (el, 300, 0, -100); }; ④监听激活索引变化:通过watch监听currentIndex,当索引变化时调用initLeftScroll,确保左侧激活项始终可见。 ( , (newIndex) => { initLeftScroll(newIndex); }); 3. 修复底部跳转问题:添加底部占位元素,调整高度。 1)添加底部占位元素:在右侧菜单容器(.menu-right的ul)中添加cate-bottom元素作为占位,避免底部内容被遮挡。 <div class="menu-right" ref="itemList"> <ul> <!-- 原有分类li --> <li class="cate-bottom"></li> <!-- 底部占位 --> </ul> </div> 2)调整占位元素高度:编写RightHeightFix函数,获取占位元素并设置高度为右侧容器高度的 1/1.2(适配底部交互区域)。 <script setup> ……(原有代码) const RightHeightFix = () => { let bottom = itemList.value.getElementsByClassName('cate-bottom')[0] bottom.style.height = itemList.value.clientHeight / 1.2 + 'px' } </script> 3)组件挂载时执行修复:在onMounted钩子中,调用RightHeightFix(确保DOM渲染完成后设置高度)。 onMounted(() => { loadCategoryList() nextTick(() => { () }) })
最新发布
11-30
### Vue3 中滚动后点击事件失效及 Input 不可用的解决方案 在 Vue3 开发过程中,如果遇到页面滚动后点击事件失效或者 `Input` 框无法正常使用的情况,通常是因为第三方库(如 BetterScroll 或者其他自定义滚动逻辑)接管了 DOM 的行为,从而阻止了默认事件传播。 以下是针对该问题的具体分析和解决方案: #### 1. **BetterScroll 导致点击事件失效** 当使用 BetterScroll 进行滚动管理时,默认情况下它会禁用原生的点击事件。这是因为 BetterScroll 默认认为触摸屏设备上的点击可能是误触,因此将其关闭以优化性能。 解决方法是在初始化 BetterScroll 实例时设置参数 `{ click: true }` 来启用点击功能[^1]: ```javascript this.scroll = new Bscroll(this.$refs.wrapper, { click: true }); ``` 通过此配置,可以重新激活被 BetterScroll 阻止的点击事件。 --- #### 2. **输入框 (Input) 失效的原因** 对于 Element UI 或其他框架中的 `el-input` 组件,在某些浏览器环境下可能会因为滚动容器捕获了焦点而使输入框失去交互能力。特别是在 IE9 等老旧浏览器中,这种现象更为明显[^1]。 为了修复这一问题,可以通过以下方式调整: ##### 方法一:手动聚焦到输入框 可以在滚动完成后强制让输入框获取焦点。例如: ```javascript nextTick(() => { const inputElement = document.querySelector('.your-input-selector'); if (inputElement) { inputElement.focus(); } }); ``` 此处需要注意的是,确保选择器 `.your-input-selector` 能够唯一匹配目标输入框。 ##### 方法二:修改 BetterScroll 参数 除了开启点击支持外,还可以尝试增加如下选项来改善兼容性: ```javascript this.scroll = new Bscroll(this.$refs.wrapper, { preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ // 对特定标签放行默认行为 }, click: true, tap: true }); ``` 这样能够允许表单控件正常工作而不受干扰。 --- #### 3. **Vue3 SFC 结构下的实现示例** 假设我们正在构建一个基于 Vue3 和 Composition API 的项目,则完整的代码可能看起来像下面这样[^2]: ```html <template> <div ref="wrapper"> <!-- 输入框 --> <el-input v-model="inputValue" placeholder="请输入内容"></el-input> <!-- 图表或其他可滚动区域 --> <BarChart id="barChart" height="400px" width="300px"/> </div> </template> <script setup lang="ts"> import { onMounted, nextTick, ref } from 'vue'; import * as BScroll from '@better-scroll/core'; import BarChart from './components/BarChart.vue'; const wrapper = ref(null); let scrollInstance; onMounted(() => { scrollInstance = new BScroll(wrapper.value, { click: true, // 启用点击 probeType: 3, // 动态监测滚动状态 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ }, // 放行指定标签的行为 }); // 可选:处理滚动完成后的回调函数 scrollInstance.on('scrollEnd', () => { focusOnInput(); // 自动聚焦至输入框 }); }); // 辅助方法 - 手动聚焦 function focusOnInput() { nextTick(() => { const inputElm = document.querySelector('.el-input__inner'); // 假设 el-input 使用默认类名 if (inputElm && !document.activeElement.isSameNode(inputElm)) { inputElm.focus(); } }); } defineProps({ inputValue: String, }); </script> ``` 以上代码展示了如何结合 BetterScrollVue3 的响应式特性解决问题,并提供了额外的功能扩展点。 --- ### 性能注意事项 - 如果应用涉及大量动态加载的内容,请考虑分页渲染策略减少内存占用。 - 在销毁组件前记得调用 `scroll.destroy()` 清理实例资源以免造成泄漏。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值