Skip to content

页面滚动锁定

在页面展示弹窗时,通常需要禁止当前页面的滚动。然而,一直以来针对这个问题并没有很好的解决方案。现在,我们找到了一个相对完美的解决方案。

基本使用

通过简单的代码添加,即可在展示弹窗时禁止页面滚动:

vue
<script setup>
import {useLockPageScroll} from '@ifanrx/uni-mp'

const {pageScrollLocked, pageMetaStyle} = useLockPageScroll()
</script>

<template>
  <!-- 该标签仅在微信小程序生效,其他端自行查阅 -->
  <page-meta :page-style="pageMetaStyle" />
</template>
<script setup>
import {useLockPageScroll} from '@ifanrx/uni-mp'

const {pageScrollLocked, pageMetaStyle} = useLockPageScroll()
</script>

<template>
  <!-- 该标签仅在微信小程序生效,其他端自行查阅 -->
  <page-meta :page-style="pageMetaStyle" />
</template>

我们对以下组件进行了处理,当它们被展示时,会标记当前页面为滚动锁定状态:

  • mp-popup
  • mp-dialog
  • mp-floating-panel
  • mp-uploader(图片裁剪时)

如果你使用的组件不在上述列表中但需要进行标记,可以按如下方式操作:

js
const {setPageScrollLocked} = useLockPageScroll()

// 弹窗展示时调用
setPageScrollLocked(true)
// 弹窗隐藏时调用
setPageScrollLocked(false)
const {setPageScrollLocked} = useLockPageScroll()

// 弹窗展示时调用
setPageScrollLocked(true)
// 弹窗隐藏时调用
setPageScrollLocked(false)

TIP

考虑到可能存在多个嵌套弹窗的情况,setPageScrollLocked(false) 并不会直接将 pageScrollLocked 设为 false。它本质上是操作一个栈,当传入一个 false 时,会与之前传入的 true 进行抵消,仅当所有 true 被抵消后,pageScrollLocked 才会变为 false。

区分上下文

在复杂的页面中,例如下面展示的含有多个选项卡的页面,每个选项卡都可能会展示弹窗。但是,我们希望它们之间相互独立,即在当前选项卡展示弹窗时,页面应该禁止滚动;当切换到另一个选项卡时,页面应该允许滚动,再次切换回之前的选项卡时,页面应该再次禁止滚动。

我们可以利用 context 上下文来区分不同选项卡,使每个选项卡的滚动锁定状态互相独立。

js
const current = ref(0)

// 在获取的时候传入 context,
// pageScrollLocked 和 setPageScrollLocked 会自动根据当前 context 进行获取和更新
const {pageScrollLocked, pageMetaStyle} = useLockPageScroll({
  context: computed(() => `tab-${current.value}`),
})
const current = ref(0)

// 在获取的时候传入 context,
// pageScrollLocked 和 setPageScrollLocked 会自动根据当前 context 进行获取和更新
const {pageScrollLocked, pageMetaStyle} = useLockPageScroll({
  context: computed(() => `tab-${current.value}`),
})

相关文档