uni-popup 弹出层
# uni-popup 弹出层
组件名:uni-popup
代码块:
uPopup
关联组件:uni-popup-dialog
,uni-popup-message
,uni-popup-share
,uni-transition
弹出层组件,在应用中弹出一个消息提示窗口、提示框等
# 介绍
注意事项
为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
- 组件需要依赖
sass
插件 ,请自行手动安装
uni-popup-message
、uni-popup-dialog
等扩展ui组件,需要和uni-popup
配套使用,暂不支持单独使用nvue
中使用uni-popup
时,尽量将组件置于其他元素后面,避免出现层级问题uni-popup
并不能完全阻止页面滚动,可在打开uni-popup
的时候手动去做一些处理,禁止页面滚动- 如果想在页面渲染完毕后就打开
uni-popup
,请在onReady
或mounted
生命周期内调用,确保组件渲染完毕 - 在微信小程序开发者工具中,启用真机调试,popup 会延时出现,是因为 setTimeout 在真机调试中的延时问题导致的,预览和发布小程序不会出现此问题
- 使用
npm
方式引入组件,如果确认引用正确,但是提示未注册组件或显示不正常,请尝试重新编译项目 uni-popup
中尽量不要使用scroll-view
嵌套过多的内容,可能会影响组件的性能,导致组件无法打开或者打开卡顿uni-popup
不会覆盖原生 tabbar 和原生导航栏uni-popup
为了防止快速打开关闭的情况,组件默认设置了300毫秒延迟显示,如果需要去除,可到uni_modules下修改组件代码- app-vue 中组件无法遮盖 video ,ad 等原生组件 ,建议使用 nvue
- 组件支持 nvue ,需要在
manifest.json > app-plus
节点下配置"nvueStyleCompiler" : "uni-app"
# 基本用法
<template>
<view>
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="bottom" border-radius="10px 10px 0 0">底部弹出 Popup 自定义圆角</uni-popup>
</view>
</template>
<script>
export default {
methods:{
open(){
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
this.$refs.popup.open('top')
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 设置主窗口背景色
在大多数场景下,并不需要设置 background-color
属性,因为uni-popup
的主窗口默认是透明的,在向里面插入内容的时候 ,样式完全交由用户定制,如果设置了背景色 ,例如 uni-popup-dialog
中的圆角就很难去实现,不设置背景色,更适合用户去自由发挥。
而也有特例,需要我们主动去设置背景色,例如 type = 'bottom'
的时候 ,在异型屏中遇到了底部安全区问题(如 iphone 11),因为 uni-popup
的主要内容避开了安全区(设置safe-area:true
),导致底部的颜色我们无法自定义,这时候使用 background-color
就可以解决这个问题。
底部弹窗示例
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="bottom" background-color="#fff">底部弹出 Popup</uni-popup>
2
# 禁用打开动画
在某些场景 ,可能不希望弹层有动画效果 ,只需要将 animation
属性设置为 false
即可以关闭动画。
居中弹窗示例
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="center" :animation="false">中间弹出 Popup</uni-popup>
2
# 禁用点击遮罩关闭
默认情况下,点击遮罩会自动关闭uni-popup
,如不想点击关闭,只需将mask-click
设置为false
,这时候要关闭uni-popup
,只能手动调用 close
方法。
示例
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" :mask-click="false">
<text>Popup</text>
<button @click="close">关闭</button>
</uni-popup>
2
3
4
5
export default {
data() {
return {}
},
onReady() {},
methods: {
open() {
this.$refs.popup.open('top')
},
close() {
this.$refs.popup.close()
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# API
# Popup Props
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
animation | Boolean | true | 是否开启动画 |
type | String | 'center' | 弹出方式 |
mask-click [即将废弃] | Boolean | true | 蒙版点击是否关闭弹窗 |
is-mask-click [1.7.4新增] | Boolean | true | 蒙版点击是否关闭弹窗 |
mask-background-color [1.7.4新增] | rgba | rgba(0,0,0,0.4) | 蒙版颜色,建议使用 rgba 颜色值 |
background-color | String | 'none' | 主窗口背景色 |
borderRadius | String | 无 | 设置圆角(左上、右上、右下和左下) 示例:"10px 10px 10px 10px" |
safe-area | Boolean | true | 是否适配底部安全区 |
# Type Options
属性名 | 说明 |
---|---|
top | 顶部弹出 |
center | 居中弹出 |
bottom | 底部弹出 |
left | 左侧弹出 |
right | 右侧弹出 |
message | 预置样式 :消息提示 |
dialog | 预置样式 :对话框 |
share | 预置样式 :底部弹出分享示例 |
# Popup Methods
方法称名 | 说明 | 参数 |
---|---|---|
open | 打开弹出层 | open(String:type) ,如果参数可代替 type 属性 |
close | 关闭弹出层 | - |
# Popup Events
事件称名 | 说明 | 返回值 |
---|---|---|
change | 组件状态发生变化触发 | e={show: true|false,type:当前模式} |
maskClick | 点击遮罩层触发 | - |
# 扩展组件说明
uni-popup
其实并没有任何样式,只提供基础的动画效果,给用户一个弹出层解决方案,仅仅是这样并不能满足开发需求,所以我们提供了三种基础扩展样式
# uni-popup-message 提示信息
将 uni-popup
的type
属性改为 message
,并引入对应组件即可使用消息提示 ,该组件不支持单独使用
示例
<uni-popup ref="popup" type="message">
<uni-popup-message type="success" message="成功消息" :duration="2000"></uni-popup-message>
</uni-popup>
2
3
# PopupMessage Props
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
type | String | success | 消息提示主题 |
message | String | - | 消息提示文字 |
duration | Number | 3000 | 消息显示时间,超过显示时间组件自动关闭,设置为0 将不会关闭,需手动调用 close 方法关闭 |
# Type Options
属性名 | 说明 |
---|---|
success | 成功 |
warn | 警告 |
error | 失败 |
info | 消息 |
# PopupMessage Slots
名称 | 说明 |
---|---|
default | 消息内容,会覆盖 message 属性 |
# uni-popup-dialog 对话框
将 uni-popup
的type
属性改为 dialog
,并引入对应组件即可使用对话框 ,该组件不支持单独使用
示例
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="dialog">
<uni-popup-dialog mode="input" message="成功消息" :duration="2000" :before-close="true" @close="close" @confirm="confirm"></uni-popup-dialog>
</uni-popup>
2
3
4
export default {
methods: {
open() {
this.$refs.popup.open()
},
/**
* 点击取消按钮触发
* @param {Object} done
*/
close() {
// TODO 做一些其他的事情,before-close 为true的情况下,手动执行 close 才会关闭对话框
// ...
this.$refs.popup.close()
},
/**
* 点击确认按钮触发
* @param {Object} done
* @param {Object} value
*/
confirm(value) {
// 输入框的值
console.log(value)
// TODO 做一些其他的事情,手动执行 close 才会关闭对话框
// ...
this.$refs.popup.close()
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# PopupDialog Props
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
type | String | success | 对话框标题主题,可选值: success/warn/info/error |
mode | String | base | 对话框模式,可选值:base(提示对话框)/input(可输入对话框) |
title | String | - | 对话框标题 |
content | String | - | 对话框内容,base模式下生效 |
confirmText [1.7.4新增] | String | - | 定义确定按钮文本 |
cancelText [1.7.4新增] | String | - | 定义取消按钮文本 |
maxlength [1.8.6新增] | Number | - | 限制输入框字数(当mode="input"时生效) |
showClose [1.8.5新增] | Boolean | - | 是否显示取消按钮 |
value | String\Number | - | 输入框值,input模式下生效 注:1.9.0之后为双向绑定,vue2通过value,vue3通过v-model绑定 |
placeholder | String | - | 输入框提示文字,input模式下生效 |
borderRadius | String | - | 四周圆角值(左上、右上、右下、左下) 示例:"20px 20px 20px 20px" |
before-close | Boolean | false | 是否拦截按钮事件,如为true,则不会关闭对话框,关闭需要手动执行 uni-popup 的 close 方法 |
# PopupDialog Events
事件称名 | 说明 | 返回值 |
---|---|---|
close | 点击dialog取消按钮触发 | - |
confirm | 点击dialog确定按钮触发 | e={value:input模式下输入框的值} |
# PopupDialog Slots
名称 | 说明 |
---|---|
default | 自定义内容,会覆盖原有的内容显示 |
# uni-popup-share 分享示例
分享示例,不作为最终可使用的组件,只做为样式组件,供用户自行修改,后续的开发计划是实现实际的分享逻辑,参数可配置
。
将 uni-popup
的 type
属性改为 share
,并引入对应组件即可使用 ,该组件不支持单独使用
# 示例
<uni-popup ref="popup" type="share">
<uni-popup-share title="分享到" @select="select"></uni-popup-share>
</uni-popup>
2
3
# PopupShare Props
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
title | String | - | 分享弹窗标题 |
before-close | Boolean | false | 是否拦截按钮事件,如为true,则不会关闭对话框,关闭需要手动执行 uni-popup 的 close 方法 |
# PopupShare Events
事件称名 | 说明 | 返回值 |
---|---|---|
select | 选择触发 | e = {item,index}:所选参数 |
# 注意
- share 分享组件,只是作为一个扩展示例,如果需要修改数据源,请到组件内修改
# 禁止滚动穿透
使用组件时,会发现内容部分滚动到底时,继续划动会导致底层页面的滚动,这就是滚动穿透。
但由于平台自身原因,除了h5平台外 ,其他平台都不能在在组件内禁止滚动穿透,所以在微信小程序、App 平台,页面内需要用户特殊处理一下
# 微信小程序/App
在 微信小程序/App
平台可使用 page-meta
组件动态修改页面样式 ,
需要在 data 中定义一个变量,用来表示 uni-popup
的开启关闭状态,并通过这个变量修改 page-meta
的 overflow
属性。
在 uni-popup
的 @change
事件中可以接受到 uni-popup
的开启关闭状态 ,并赋值给上面的变量
下面是关键代码片段:
<template>
<page-meta :page-style="'overflow:'+(show?'hidden':'visible')"></page-meta>
<view class="container">
<!-- 普通弹窗 -->
<uni-popup ref="popup" background-color="#fff" @change="change">
<!-- ... -->
</uni-popup>
</view>
</template>
<script>
export default {
data() {
return {
show:false
}
},
methods: {
change(e) {
this.show = e.show
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# tips
- h5 滚动穿透不需要处理
- wx、app 需要 使用 page-meta 组件配合阻止滚动穿透
- 注意 page-meta 组件,一个页面只能存在一个
- 其他平台无法阻止滚动穿透,建议使用 scroll-view 滚动 ,手动设置 overflow:hidden,同 page-meta 方法一致
# 示例
注意
示例依赖了 uni-card
uni-section
uni-scss
等多个组件,直接拷贝示例代码将无法正常运行 。
请到 组件下载页面 (opens new window) ,在页面右侧选择 使用 HBuilderX导入示例项目
,体验完整示例演示 (opens new window)。
<template>
<view class="container">
<uni-card is-full :is-shadow="false">
<text class="uni-h6">弹出层组件用于弹出一个覆盖到页面上的内容,使用场景如:底部弹出分享弹窗、页面插屏广告等。</text>
</uni-card>
<uni-section title="基本示例" type="line">
<view class="example-body box">
<button class="button" type="primary" @click="toggle('top')"><text class="button-text">顶部</text></button>
<button class="button" type="primary" @click="toggle('bottom')"><text class="button-text">底部</text></button>
<button class="button" type="primary" @click="toggle('center')"><text class="button-text">居中</text></button>
<button class="button" type="primary" @click="toggle('left')"><text class="button-text">左侧</text></button>
<button class="button" type="primary" @click="toggle('right')"><text class="button-text">右侧</text></button>
</view>
</uni-section>
<uni-section title="提示消息" type="line">
<view class="example-body box">
<button class="button popup-success" @click="messageToggle('success')"><text
class="button-text success-text">成功</text></button>
<button class="button popup-error" @click="messageToggle('error')"><text
class="button-text error-text">失败</text></button>
<button class="button popup-warn" @click="messageToggle('warn')"><text
class="button-text warn-text">警告</text></button>
<button class="button popup-info" @click="messageToggle('info')"><text
class="button-text info-text">信息</text></button>
</view>
</uni-section>
<uni-section title="对话框示例" type="line" class="hideOnPc">
<view class="example-body box">
<button class="button popup-success" @click="dialogToggle('success')"><text
class="button-text success-text">成功</text></button>
<button class="button popup-error" @click="dialogToggle('error')"><text
class="button-text error-text">失败</text></button>
<button class="button popup-warn" @click="dialogToggle('warn')"><text
class="button-text warn-text">警告</text></button>
<button class="button popup-info" @click="dialogToggle('info')"><text
class="button-text info-text">信息</text></button>
</view>
</uni-section>
<uni-section title="输入框示例" type="line" padding>
<view class="dialog-box">
<text class="dialog-text">输入内容:{{ value }}</text>
</view>
<button class="button" type="primary" @click="inputDialogToggle"><text
class="button-text">输入对话框</text></button>
</uni-section>
<uni-section title="底部分享示例" type="line" padding>
<button class="button" type="primary" @click="shareToggle"><text class="button-text">分享模版示例</text></button>
</uni-section>
<view>
<!-- 普通弹窗 -->
<uni-popup ref="popup" background-color="#fff" @change="change">
<view class="popup-content" :class="{ 'popup-height': type === 'left' || type === 'right' }"><text
class="text">popup 内容</text></view>
</uni-popup>
</view>
<view>
<!-- 提示信息弹窗 -->
<uni-popup ref="message" type="message">
<uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
</uni-popup>
</view>
<view>
<!-- 提示窗示例 -->
<uni-popup ref="alertDialog" type="dialog">
<uni-popup-dialog :type="msgType" cancelText="关闭" confirmText="同意" title="通知" content="欢迎使用 uni-popup!" @confirm="dialogConfirm"
@close="dialogClose"></uni-popup-dialog>
</uni-popup>
</view>
<view>
<!-- 输入框示例 -->
<uni-popup ref="inputDialog" type="dialog">
<uni-popup-dialog ref="inputClose" mode="input" title="输入内容" value="对话框预置提示内容!"
placeholder="请输入内容" @confirm="dialogInputConfirm"></uni-popup-dialog>
</uni-popup>
</view>
<view>
<!-- 分享示例 -->
<uni-popup ref="share" type="share" safeArea backgroundColor="#fff">
<uni-popup-share></uni-popup-share>
</uni-popup>
</view>
</view>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<script>
export default {
data() {
return {
type: 'center',
msgType: 'success',
messageText: '这是一条成功提示',
value: ''
}
},
onReady() {},
methods: {
change(e) {
console.log('当前模式:' + e.type + ',状态:' + e.show);
},
toggle(type) {
this.type = type
// open 方法传入参数 等同在 uni-popup 组件上绑定 type属性
this.$refs.popup.open(type)
},
messageToggle(type) {
this.msgType = type
this.messageText = `这是一条${type}消息提示`
this.$refs.message.open()
},
dialogToggle(type) {
this.msgType = type
this.$refs.alertDialog.open()
},
dialogConfirm() {
console.log('点击确认')
this.messageText = `点击确认了 ${this.msgType} 窗口`
this.$refs.message.open()
},
inputDialogToggle() {
this.$refs.inputDialog.open()
},
dialogClose() {
console.log('点击关闭')
},
dialogInputConfirm(val) {
uni.showLoading({
title: '3秒后会关闭'
})
setTimeout(() => {
uni.hideLoading()
console.log(val)
this.value = val
// 关闭窗口后,恢复默认内容
this.$refs.inputDialog.close()
}, 3000)
},
shareToggle() {
this.$refs.share.open()
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<style lang="scss">
@mixin flex {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
@mixin height {
/* #ifndef APP-NVUE */
height: 100%;
/* #endif */
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
}
.box {
@include flex;
}
.button {
@include flex;
align-items: center;
justify-content: center;
flex: 1;
height: 35px;
margin: 0 5px;
border-radius: 5px;
}
.example-body {
background-color: #fff;
padding: 10px 0;
}
.button-text {
color: #fff;
font-size: 12px;
}
.popup-content {
@include flex;
align-items: center;
justify-content: center;
padding: 15px;
height: 50px;
background-color: #fff;
}
.popup-height {
@include height;
width: 200px;
}
.text {
font-size: 12px;
color: #333;
}
.popup-success {
color: #fff;
background-color: #e1f3d8;
}
.popup-warn {
color: #fff;
background-color: #faecd8;
}
.popup-error {
color: #fff;
background-color: #fde2e2;
}
.popup-info {
color: #fff;
background-color: #f2f6fc;
}
.success-text {
color: #09bb07;
}
.warn-text {
color: #e6a23c;
}
.error-text {
color: #f56c6c;
}
.info-text {
color: #909399;
}
.dialog,
.share {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.dialog-box {
padding: 10px;
}
.dialog .button,
.share .button {
/* #ifndef APP-NVUE */
width: 100%;
/* #endif */
margin: 0;
margin-top: 10px;
padding: 3px 0;
flex: 1;
}
.dialog-text {
font-size: 14px;
color: #333;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Make sure to add code blocks to your code group