uniapp  vue  nvue 模态框遮罩

以前 纯 Vue 开发的时候:模态框遮罩就是这么写的

android自定义遮罩_uni-app

.popBack{
    position: fixed;
    top: 0;
    left: 0;
    z-index: 999;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.4);
}

完全OK, 没问题, 可以全部覆盖 显示区域

现在使用 uniapp 混合开发的时候, 有使用到 一些原生的东西,(titleNView,tabBar 采用原生 官方推荐) 会发生这样的情况

比如说:开发左    真机右

android自定义遮罩_css_02

android自定义遮罩_作用域_03

android自定义遮罩_android自定义遮罩_04

android自定义遮罩_uni-app_05

 

反正 就是 Vue 的界面 不能遮挡 原生组件, 这样在需要 模态的 地方就很尴尬。

 

后来进过 翻查资料发现, Uniapp 给大家 提供了几种方式, 其中一个叫  .nvue , subNVues 的形式支持 全屏模态

例如这样的效果, 可以覆盖掉原生组件

android自定义遮罩_作用域_06

但是呢: .nvue 语法呢 是 css 的 阉割版,

nvue 页面均采用 flex 布局,不支持其他布局方式,需要注意的是 flex 默认为竖向排列,即 flex-direction: column。nvue 的各组件在安卓端默认是透明的,如果不设置background-color,可能会导致出现重影的问题。 在 App.vue 中定义的全局样式不会在 nvue 页面生效。 nvue 切换横竖屏时可能重新计算 px,导致样式出现问题,建议有 nvue 的页面锁定手机方向。 目前不支持在 nvue 页面使用 scss、less 等预编译语言。 不能在 style 中引入字体文件,nvue 中字体图标的使用参考:weex 加载自定义字体。 class 进行绑定时只支持数组语法(weex 限制)。 nvue 页面跳转 vue 页面时,只能调用 uni-app 的 路由 API 进行跳转。 nvue 暂不支持运行在模拟器上。 在 created 里调用 uni-app 的 api 时,可能出现 launch webview id is not ready 错误,延时几百毫秒再执行就不会报错了。 nvue 页面 titleNview 设为 false时,想要模拟状态栏,可以参考:https://ask.dcloud.net.cn/article/35111。 nvue 中不支持使用 import 的方式引入外部 css,需使用如下方式进行引入,注意:引入外部 css 的 style 节点下写样式是不会生效的,需要额外添加新的 style 节点。

 具体使用是这样的: 在 pages.json 中进行配置。

android自定义遮罩_uni-app_07

{
    "path": "pages/home/home",
    "style": {
        "navigationBarTitleText": "首页",
        "enablePullDownRefresh": true,
        "backgroundColor": "#ebebeb;",
        "backgroundColorBottom": "#ebebeb;",
        "backgroundColorTop": "#ebebeb;",
        "app-plus": {
            "bounce": "none",
            "titleNView": {
                "titleColor": "#fff",
                // "height": "55px",
                "buttons": [{
                    "float": "left",
                    "text": "回款日历",
                    "fontSize": "17px",
                    "width": "auto"
                }, {
                    "bottom": "10px",
                    "float": "right",
                    "text": "签到",
                    "fontSize": "17px",
                    "width": "auto"

                }]
            },
            "subNVues": [{
                "id": "calendar", // 唯一标识 
                "path": "pages/home/subnvue/calendar", // 页面路径  
                "type": "popup", //这里不需要
                "style": {
                    "margin": "auto",
                    "width": "85%",
                    "height": "860upx",
                    "border-radius": "10upx"
                }
            }]
        }
    }

}

 这里是  .nvue 的内容

<template>
	<div class="calendar">
		<div class="top-box">
			<image class="top-box-imagesleft" src="../../../static/img/common/youqiehuan@2x_03.png" mode="" @tap="onDateBefore()"></image>
			<text style="color: #FFFFFF; font-size: 30upx; width: 200rpx;text-align: center;">{{titleTime}}</text>
			<image class="top-box-imagesright" src="../../../static/img/common/zuoqiehuan@2x_03.png" mode="" @tap="onDateAfter()"></image>
		</div>
		<div class="mid-box">
			<div class="mid-box-days">
				<text style="color: #969696; font-size: 26upx;" v-for="(day, index) in days" :key="index">{{day}}</text>
			</div>
			<div class="mid-box-listday">
				<div class="day-line-one" v-for="(itemlist,index) in singMesh" :key="index">
					<div class="dayitem" v-for="item in itemlist" :key="item.index">
						<div class="item-background" :class="[item.isToday?'item-background-red':'']">
							<div class="item-dayInfo">
								<text style="color: #ffffff; font-size: 32upx;text-align: center; margin-top: 25rpx;margin-left: 10rpx;width: 40rpx; height: 100%"
								 v-if="item.isToday">{{item.day}}</text>
								<text style="color: #3f3f3f; font-size: 32upx;text-align: center; margin-top: 25rpx;margin-left: 10rpx;width: 40rpx; height: 100%"
								 v-if="!item.isToday">{{item.day}}</text>
								<div class="item-signInfo" v-if="item.datum">
									<text style="color: #d80e1d; font-size: 18rpx; height: 30rpx;width: 30rpx; text-align: center;line-height: 30rpx">+{{item.datum.score}}
									</text>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
		<div class="bottom-box">
			<div class="singbutton">
				<text style="color: #FFFFFF; text-align: center;line-height: 88rpx;height: 88rpx;font-size: 32rpx" @tap="onSign()">{{onSignMSG}}</text>
			</div>
			<text style="color: #969696; text-align: center;line-height: 88rpx;height: 88rpx;font-size: 26rpx">已连续签到{{continueDays}}天</text>
			<text style="color: #1168cf; text-align: center;line-height: 50rpx;height: 50rpx;font-size: 26rpx">不再提示?</text>
		</div>
	</div>
</template>

<script>
	//当前脚本隶属于 别的作用域 不可与vue 作用域 互通
	import httpHelper from '@/utils/httpHelper.js'
	import toolTimer from '@/utils/tool/toolTimer.js'
	import {
		userManager
	} from '@/utils/userData.js'
	export default {
		data() {
			return {
				days: ['日', '一', '二', '三', '四', '五', '六'],
				currentTime: new Date(),
				titleTime: '',
				singDatum: '', //当天是否签到
				singDatumDetail: {
					continuousDays: 0
				},
				//签到详情
				singMesh: [
					[],
					[],
					[],
					[],
					[],
					[],
				]
			}
		},
		created() {
			userManager.initUserData()

			// userManager.userOffLine()


			// const vm = this;
			// for (let i = 1; i < 20; i++) {
			// 	this.lists.push('item' + i);
			// }

			uni.$on('page-popup', (data) => {

			})

			if (userManager.userInfo.state) {

				//今天是否签到
				httpHelper.requestPost({
					url: "/novemAppMobile/homePageSign.do",
					data: {
						userId: userManager.getLoginData().id
					},
					success: (res) => {
						if (res.code == 0) {
							//获取成功  设置会员信息
							//console.log("今天是否签到res=====>", res)
							this.singDatum = res.object
							//当天没有签到 显示签到界面
							if (!this.singDatum.is_signed || this.singDatum.is_signed == false) {
								const subNVue = uni.getSubNVueById('calendar');
								subNVue.show('none', 250);
							}
						} else {
							uni.showModal({
								title: '签到',
								content: '' + res.msg,
								showCancel: false,
							});
						}
					}
				})



				this.currentDeta()
			}
		},
		beforeDestroy() {
			uni.$off('drawer-page')
		},
		methods: {
			//刷新签到信息
			onRefeshHomePageSign() {
				//今天是否签到
				httpHelper.requestPost({
					url: "/novemAppMobile/homePageSign.do",
					data: {
						userId: userManager.getLoginData().id
					},
					success: (res) => {
						if (res.code == 0) {
							this.singDatum = res.object
						}
					}
				})
			},
			onDateBefore() {
				this.currentTime.setMonth(this.currentTime.getMonth() - 1)
				console.log("onDateBefore:", this.currentTime)
				this.currentDeta()
			},
			onDateAfter() {
				this.currentTime.setMonth(this.currentTime.getMonth() + 1)
				console.log("onDateAfter:", this.currentTime)
				this.currentDeta()
			},
			currentDeta() {
				this.titleTime = this.currentTime.getFullYear() + '年' + (this.currentTime.getMonth() + 1) + '月'


				let allDay = new Date(this.currentTime.getFullYear(), this.currentTime.getMonth() + 1, 0); //当月总的天数
				let firstDay = new Date(this.currentTime.getFullYear(), this.currentTime.getMonth(), 1); //当月第一天信息
				let firstWeekday = firstDay.getDay(); //当月第一天是礼拜几


				httpHelper.requestPost({
					url: "/novemAppMobile/getRecordByMonthSign.do",
					data: {
						userId: userManager.getLoginData().id,
						month: toolTimer.formatTime(this.currentTime, "yyyy-M")
					},
					success: (res) => {
						if (res.code == 0) {
							//获取成功  设置会员信息
							//console.log("获取签到信息", res)
							this.singDatumDetail = res.object
							this.singDatumDetailTrim()

							this.showSingMesh({
								allDay: allDay.getDate(),
								firstWeekday: firstDay.getDay(),
								today: this.currentTime.getDate(),
								isOnMonth: toolTimer.formatTime(this.currentTime, "yyyy-MM") == toolTimer.formatTime(new Date(), "yyyy-MM") //是否是当前月份
							})

						} else {
							uni.showModal({
								title: '登陆失败',
								content: '' + res.msg,
								showCancel: false,
							});
						}
					}
				})
			},

			showSingMesh(datum) {

				this.singMesh = []
				let index = 0
				let dayInfo = {}
				let day = 1

				let time = ""


				for (let i = 0; i < 6; i++) {
					let weekDay = []
					for (let j = 0; j < 7; j++) {
						index = index + 1 //每个格子的ID
						dayInfo = {
							index: index,
							day: ' ',
							singInfo: {},
							isToday: false,
							isSelect: false,
							datum: ''
						}
						if (index > datum.firstWeekday) { //当月第一天的 星期
							if (day <= datum.allDay) { //当月多天数

								time = toolTimer.formatTime(new Date(this.currentTime.getFullYear(), this.currentTime.getMonth(), day),
									"yyyy-MM-dd")
								//console.log("time:", time)
								if (datum.isOnMonth && day == datum.today) {
									dayInfo.isToday = true
								}
								dayInfo.day = day++
								if (this.singDatumDetail.record.length) {
									dayInfo.datum = this.singDatumDetail.record.filter(x => x.time == time)[0]
								}
							}
						}
						weekDay.push(dayInfo)

					}
					this.singMesh.push(weekDay)
				}
			},
			singDatumDetailTrim() {
				this.singDatumDetail.record.forEach(item => {
					item.time = toolTimer.formatTime(new Date(item.signTime), "yyyy-MM-dd")
				})
			},

			onSign() {
				if (!this.singDatum.is_signed || this.singDatum.is_signed == false) {
					//console.log('点击签到')
					httpHelper.requestPost({
						url: "/novemAppMobile/dailySign.do",
						data: {
							userId: userManager.getLoginData().id
						},
						success: (res) => {
							if (res.code == 0) {

								this.onRefeshHomePageSign()
								uni.showToast({
									title: '签到成功',
									duration: 1500
								});
							} else {
								uni.showModal({
									title: '签到',
									content: '' + res.msg,
									showCancel: false,
								});
							}
						}
					})
				} else {
					//console.log('查看奖励')
					uni.navigateTo({
						url: '/pages/home/signedDetail'
					})
				}
			},
			sendMessage() {
				const subNVue = uni.getCurrentSubNVue()
				uni.$emit('popup-page', {
					title: '已读完!',
				})
			},
			handle(item, index) {
				const subNVue = uni.getCurrentSubNVue()
				uni.$emit('popup-page', {
					type: 'interactive',
					info: item + ' 该元素被点击了!',
				})
			}
		},
		computed: {
			continueDays() {
				return this.singDatumDetail.continuousDays
			},
			onSignMSG() {
				if (!this.singDatum.is_signed || this.singDatum.is_signed == false) {
					return '点击签到'
				} else {
					return '查看奖励'
				}
			}
		}
	}
</script>

<style>
	.calendar {
		flex-direction: column;
		align-items: center;
		/* 	//justify-content: center; */
		background-color: #FFFFFF;

		/* 		border-radius: 13rpx; */
	}



	.top-box {
		/* align-items: center; */
		flex-direction: row;
		justify-content: center;
		align-items: center;
		width: 640rpx;
		height: 88rpx;
		background-color: #d7000f;
		/* 		border-radius: 13rpx; */
	}

	.top-box-imagesleft {
		margin-right: 80rpx;
		height: 40rpx;
		width: 40rpx;
	}

	.top-box-imagesright {
		margin-left: 80rpx;
		height: 40rpx;
		width: 40rpx;
	}

	.mid-box {
		height: 476rpx;
		width: 600rpx;
		align-items: center;
		/* 		background-color: #FFB400; */
	}

	.mid-box-days {
		height: 79rpx;
		width: 540rpx;
		/* 		background-color: #6D6D72; */
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
	}

	.mid-box-listday {
		width: 600rpx;
		height: 412rpx;
		background-color: #EBEBEB;
	}

	.day-line-one {
		height: 70rpx;
		width: 600rpx;
		/* background-color: #6D6D72; */
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
	}







	.item-background-text {
		color: #FFFFFF
	}



	.dayitem {
		align-items: center;
		height: 70rpx;
		width: 84rpx;
		border-left-color: #FFFFFF;
		border-left-width: 1px;
		border-bottom-color: #FFFFFF;
		border-bottom-width: 1px;
		/* background-color: #00aa00; */
	}

	.item-background {
		margin-top: 12rpx;

		align-items: center;
		height: 50rpx;
		width: 50rpx;
		border-radius: 50%;
	}

	.item-text-white {
		color: #FFFFFF;
	}

	.item-background-red {
		align-items: center;
		background-color: #D7000F;
	}

	/* 签到信息 */
	.item-signInfo {
		height: 30rpx;
		width: 30rpx;
		margin-left: -10rpx;
		margin-top: -10rpx;
		border-radius: 50%;
		background-color: #eb8087;
		align-items: flex-end;
	}

	/* 几号 */
	.item-dayInfo {
		flex-direction: row;
		align-items: center;
		justify-content: space-around;
		height: 30rpx;
		width: 50rpx;
		margin-top: -2rpx;
		margin-left: -8rpx;

	}

	.bottom-box {
		width: 600rpx;
		height: 280rpx;
		/* 	//background-color: #007AFF; */
	}

	.singbutton {
		margin-top: 50rpx;
		width: 600rpx;
		height: 88rpx;
		background-color: #d7000f;
		border-radius: 13rpx;
	}
</style>

也就是这个界面

android自定义遮罩_uni-app_08

 

然后是让 它显示: 因为只能在真机上测试

android自定义遮罩_android自定义遮罩_09

onNavigationBarButtonTap(e) {

    if (userManager.userInfo.state) {
        if (e.index === 0) { //回款日历
            uni.navigateTo({
                url:'/pages/common/calendar/calendarMoney'
            })
        } else if (e.index === 1) { //签到

            // #ifdef APP-PLUS
            const subNVue = uni.getSubNVueById('calendar');
            subNVue.show('none', 250);
            // #endif
            
            
        }
    }

},