feat: Popup 弹出层组件增加 lock-scroll 属性

This commit is contained in:
xuqingkai 2023-10-14 10:14:41 +08:00 committed by weisheng
parent 41b2c4f367
commit a6987e65da
4 changed files with 159 additions and 25 deletions

View File

@ -27,6 +27,52 @@
<wd-popup v-model="show" position="bottom" closable custom-style="height: 200px;" @close="handleClose"></wd-popup> <wd-popup v-model="show" position="bottom" closable custom-style="height: 200px;" @close="handleClose"></wd-popup>
``` ```
## 禁用遮罩点击
通过设置 `close-on-click-modal` 属性为 `false`,你可以禁用用户点击遮罩层时关闭弹出层的功能。
```html
<wd-popup v-model="show7" position="bottom" :close-on-click-modal="false" closable custom-style="height: 200px;" @close="handleClose7"></wd-popup>
```
## 禁用遮罩
通过设置 `modal` 属性为 `false`,你可以禁用遮罩层,使用户可以与底层内容进行交互。
```html
<wd-popup v-model="show8" position="bottom" :modal="false" closable custom-style="height: 200px;" @close="handleClose8"></wd-popup>
```
## 开启底部安全区
通过设置 `safe-area-inset-bottom` 属性为 `true`,你可以确保弹出层在底部显示时不会被底部安全区域遮挡。
```html
<wd-popup v-model="show9" position="bottom" :safe-area-inset-bottom="true" custom-style="height: 200px;" @close="handleClose9"></wd-popup>
```
## 禁止滚动穿透
使用组件时,会发现内容部分滚动到底时,继续划动会导致底层页面的滚动,这就是滚动穿透。
目前,组件可以通过 `lock-scroll` 属性处理部分滚动穿透问题。 但由于小程序和APP平台自身原因弹窗内容区域仍会出现滚动穿透。 不过,我们为开发者提供了一个推荐方案以完整解决滚动穿透:
可以使用 [page-meta](https://uniapp.dcloud.net.cn/component/page-meta#page-meta) 组件动态修改 `page-meta``overflow` 属性。
```html
<!-- page-meta 只能是页面内的第一个节点 -->
<page-meta :page-style="`overflow:${show10 ? 'hidden' : 'visible'};`"></page-meta>
<wd-popup v-model="show10" lock-scroll position="bottom" :safe-area-inset-bottom="true" custom-style="height: 200px;" @close="handleClose10"></wd-popup>
```
:::tip 提示
h5 滚动穿透不需要处理,组件已默认开启 `lock-scroll`
:::
### H5平台
## Attributes ## Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
@ -43,19 +89,20 @@
| hide-when-close | 是否当关闭时将弹出层隐藏display: none) | boolean | - | true | - | | hide-when-close | 是否当关闭时将弹出层隐藏display: none) | boolean | - | true | - |
| lazy-render | 弹层内容懒渲染,触发展示时才渲染内容 | boolean | - | true | - | | lazy-render | 弹层内容懒渲染,触发展示时才渲染内容 | boolean | - | true | - |
| safe-area-inset-bottom | 弹出面板是否设置底部安全距离iphone X 类型的机型) | boolean | - | false | - | | safe-area-inset-bottom | 弹出面板是否设置底部安全距离iphone X 类型的机型) | boolean | - | false | - |
| lockScroll | 是否锁定背景滚动 | boolean | - | true | 0.1.30 |
## Events ## Events
| 事件名称 | 说明 | 参数 | 最低版本 | | 事件名称 | 说明 | 参数 | 最低版本 |
|---------|-----|-----|---------| |---------|-----|-----|---------|
| close | 弹出层关闭时触发 | - | - | | close | 弹出层关闭时触发 | - | - |
| clickmodal | 点击遮罩时触发 | - | - | | click-modal | 点击遮罩时触发 | - | - |
| beforeenter | 进入前触发 | - | - | | before-enter | 进入前触发 | - | - |
| enter | 进入时触发 | - | - | | enter | 进入时触发 | - | - |
| afterenter | 进入后触发 | - | - | | after-enter | 进入后触发 | - | - |
| beforeleave | 离开前触发 | - | - | | before-leave | 离开前触发 | - | - |
| leave | 离开时触发 | - | - | | leave | 离开时触发 | - | - |
| afterleave | 离开后触发| - | - | | after-leave | 离开后触发| - | - |
## 外部样式类 ## 外部样式类

View File

@ -60,7 +60,7 @@ const list = ref([
}, },
{ {
id: 'configProvider', id: 'configProvider',
name: 'configProvider 全局配置' name: 'ConfigProvider 全局配置'
}, },
{ {
id: 'popup', id: 'popup',

View File

@ -1,26 +1,57 @@
<!-- <!--
* @Author: weisheng * @Author: weisheng
* @Date: 2023-08-01 11:12:05 * @Date: 2023-08-01 11:12:05
* @LastEditTime: 2023-08-15 11:54:31 * @LastEditTime: 2023-10-13 18:45:34
* @LastEditors: weisheng * @LastEditors: weisheng
* @Description: * @Description:
* @FilePath: \wot-design-uni\src\pages\popup\Index.vue * @FilePath: \wot-design-uni\src\pages\popup\Index.vue
* 记得注释 * 记得注释
--> -->
<template> <template>
<page-meta :page-style="`overflow:${show10 ? 'hidden' : 'visible'};`"></page-meta>
<view> <view>
<page-wraper> <page-wraper>
<demo-block title="基本用法"> <demo-block title="基础用法" transparent>
<wd-button @click="handleClick1">弹出层</wd-button> <wd-cell-group>
<wd-cell title="弹出层" is-link @click="handleClick1" />
</wd-cell-group>
</demo-block> </demo-block>
<demo-block title="弹出位置"> <demo-block title="弹出位置" transparent>
<wd-button @click="handleClick2">顶部</wd-button> <wd-cell-group border>
<wd-button @click="handleClick3">右侧</wd-button> <wd-cell title="顶部" is-link @click="handleClick2" />
<wd-button @click="handleClick4">底部</wd-button> <wd-cell title="右侧" is-link @click="handleClick3" />
<wd-button @click="handleClick5">左侧</wd-button> <wd-cell title="底部" is-link @click="handleClick4" />
<wd-cell title="左侧" is-link @click="handleClick5" />
</wd-cell-group>
</demo-block> </demo-block>
<demo-block title="关闭按钮"> <demo-block title="关闭按钮" transparent>
<wd-button @click="handleClick6">关闭按钮</wd-button> <wd-cell-group border>
<wd-cell title="关闭按钮" is-link @click="handleClick6" />
</wd-cell-group>
</demo-block>
<demo-block title="锁定滚动" transparent>
<wd-cell-group border>
<wd-cell title="锁定滚动" is-link @click="handleClick10" />
</wd-cell-group>
</demo-block>
<demo-block title="禁用遮罩点击" transparent>
<wd-cell-group border>
<wd-cell title="禁用遮罩点击" is-link @click="handleClick7" />
</wd-cell-group>
</demo-block>
<demo-block title="禁用遮罩" transparent>
<wd-cell-group border>
<wd-cell title="禁用遮罩" is-link @click="handleClick8" />
</wd-cell-group>
</demo-block>
<demo-block title="开启底部安全区" transparent>
<wd-cell-group border>
<wd-cell title="开启底部安全区" is-link @click="handleClick9" />
</wd-cell-group>
</demo-block> </demo-block>
<wd-popup v-model="show1" custom-style="padding: 30px 40px;" @close="handleClose1"><text class="custom-txt">内容</text></wd-popup> <wd-popup v-model="show1" custom-style="padding: 30px 40px;" @close="handleClose1"><text class="custom-txt">内容</text></wd-popup>
@ -29,6 +60,25 @@
<wd-popup v-model="show4" position="bottom" custom-style="height: 200px;" @close="handleClose4"></wd-popup> <wd-popup v-model="show4" position="bottom" custom-style="height: 200px;" @close="handleClose4"></wd-popup>
<wd-popup v-model="show5" position="left" custom-style="width: 200px;" @close="handleClose5"></wd-popup> <wd-popup v-model="show5" position="left" custom-style="width: 200px;" @close="handleClose5"></wd-popup>
<wd-popup v-model="show6" position="bottom" closable custom-style="height: 200px;" @close="handleClose6"></wd-popup> <wd-popup v-model="show6" position="bottom" closable custom-style="height: 200px;" @close="handleClose6"></wd-popup>
<wd-popup
v-model="show7"
position="bottom"
:close-on-click-modal="false"
closable
custom-style="height: 200px;"
@close="handleClose7"
></wd-popup>
<wd-popup v-model="show8" position="bottom" :modal="false" closable custom-style="height: 200px;" @close="handleClose8"></wd-popup>
<wd-popup v-model="show9" position="bottom" :safe-area-inset-bottom="true" custom-style="height: 200px;" @close="handleClose9"></wd-popup>
<wd-popup
v-model="show10"
lock-scroll
position="bottom"
:safe-area-inset-bottom="true"
custom-style="height: 200px;"
@close="handleClose10"
></wd-popup>
</page-wraper> </page-wraper>
</view> </view>
</template> </template>
@ -41,6 +91,7 @@ const show3 = ref<boolean>(false)
const show4 = ref<boolean>(false) const show4 = ref<boolean>(false)
const show5 = ref<boolean>(false) const show5 = ref<boolean>(false)
const show6 = ref<boolean>(false) const show6 = ref<boolean>(false)
const show7 = ref<boolean>(false)
function handleClick1() { function handleClick1() {
show1.value = true show1.value = true
@ -78,12 +129,46 @@ function handleClick6() {
function handleClose6() { function handleClose6() {
show6.value = false show6.value = false
} }
</script>
<style lang="scss" scoped> function handleClick7() {
:deep(button) { show7.value = true
margin: 0 10px 10px 0;
} }
function handleClose7() {
show7.value = false
}
const show8 = ref<boolean>(false)
function handleClick8() {
show8.value = true
}
function handleClose8() {
show8.value = false
}
const show9 = ref<boolean>(false)
function handleClick9() {
show9.value = true
}
function handleClose9() {
show9.value = false
}
const show10 = ref<boolean>(false)
function handleClick10() {
show10.value = true
}
function handleClose10() {
show10.value = false
}
</script>
<style lang="scss" scoped>
.wot-theme-dark { .wot-theme-dark {
.custom-txt { .custom-txt {
color: $-dark-color; color: $-dark-color;

View File

@ -1,8 +1,9 @@
<template> <template>
<wd-modal <wd-overlay
v-if="modal" v-if="modal"
:show="modelValue" :show="modelValue"
:z-index="zIndex" :z-index="zIndex"
:lock-scroll="lockScroll"
:duration="duration" :duration="duration"
:custom-style="modalStyle" :custom-style="modalStyle"
@click="handleClickModal" @click="handleClickModal"
@ -44,6 +45,7 @@ interface Props {
modelValue: boolean modelValue: boolean
customStyle?: string customStyle?: string
lazyRender?: boolean lazyRender?: boolean
lockScroll?: boolean
customClass?: string customClass?: string
} }
@ -59,6 +61,7 @@ const props = withDefaults(defineProps<Props>(), {
zIndex: 10, zIndex: 10,
hideWhenClose: true, hideWhenClose: true,
lazyRender: true, lazyRender: true,
lockScroll: true,
safeAreaInsetBottom: false, safeAreaInsetBottom: false,
modelValue: false modelValue: false
}) })
@ -100,14 +103,13 @@ const name = ref<string>('') // 动画名
const emit = defineEmits([ const emit = defineEmits([
'update:modelValue', 'update:modelValue',
'click',
'before-enter', 'before-enter',
'enter', 'enter',
'before-leave', 'before-leave',
'leave', 'leave',
'after-leave', 'after-leave',
'after-enter', 'after-enter',
'clickmodal', 'click-modal',
'close' 'close'
]) ])
@ -128,7 +130,7 @@ onBeforeMount(() => {
if (safeArea) { if (safeArea) {
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
safeBottom.value = screenHeight - safeArea!.bottom || 0 safeBottom.value = screenHeight - (safeArea!.bottom || 0)
// #endif // #endif
// #ifndef MP-WEIXIN // #ifndef MP-WEIXIN
safeBottom.value = safeAreaInsets ? safeAreaInsets.bottom : 0 safeBottom.value = safeAreaInsets ? safeAreaInsets.bottom : 0
@ -227,7 +229,7 @@ function observerTransition() {
} }
function handleClickModal() { function handleClickModal() {
emit('clickmodal') emit('click-modal')
if (props.closeOnClickModal) { if (props.closeOnClickModal) {
close() close()
} }