uniapp vue nvue 模态框遮罩
以前 纯 Vue 开发的时候:模态框遮罩就是这么写的
.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 采用原生 官方推荐) 会发生这样的情况
比如说:开发左 真机右
反正 就是 Vue 的界面 不能遮挡 原生组件, 这样在需要 模态的 地方就很尴尬。
后来进过 翻查资料发现, Uniapp 给大家 提供了几种方式, 其中一个叫 .nvue , subNVues 的形式支持 全屏模态
例如这样的效果, 可以覆盖掉原生组件
但是呢: .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 中进行配置。
{
"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>
也就是这个界面
然后是让 它显示: 因为只能在真机上测试
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
}
}
},