用uniapp开发app的时候经常会有以下问题:
1、覆盖原生导航栏、tabbar 的弹出层组件。比如侧滑菜单盖不住地图、视频、原生导航栏,比如 popup盖不住tabbar。
2、弹出层内部元素可滚动,
3、在map、video等组件上的添加复杂覆盖组件:比如直播视频上覆盖滚动的聊天记录
虽然有cover-view来覆盖原生组件,但是在app-vue中不支持嵌套,且只能在map、video组件使用
这个时候用原生子窗体是比较适合的
1、使用前配置page.json
在 pages.json 中,新增 subNVues 节点进行配置
全部配置表请看:原生子窗体配置表
id:作为唯一标志不能重复
path: ubNVue 子窗体的路径
type: 内置的特殊子窗体类型,弹出(popup)和导航(navigationBar)。可以不写
style: 配置子窗体的位置,背景等样式属性。
注意事项
开发区别请看:uniapp-----nvue教程
2、在页面中使用原生子窗体(这里的使用以在vue页面中为例)
在页面目录下新建专门存放原生子窗体的文件夹,subNVue是使用原生子窗体的vue页面
**
**
因为事件监听是全局的,所以使用 uni. o n , 需 要 使 用 u n i . on ,需要使用 uni. on,需要使用uni.off 移除全局的事件监听,避免重复监听,一定要记得移除监听
<template>
<view class="content">
<view class="example">
<view class="example-title">从上侧竖向滑出</view>
<button type="primary" size="mini" @click="showPopup">显示 弹出层</button>
</view>
<view>
<video style="width: 100vw" v-if="showVideo" id="video"
:controls="false"
:src="videoUrl"
></video>
</view>
</view>
</template>
<script>
export default {
data() {
return {
showVideo: false,
videoUrl: 'https://www.apple.com/105/media/cn/mac/family/2018/46c4b917_abfd_45a3_9b51_4e3054191797/films/bruce/mac-bruce-tpl-cn-2018_1280x720h.mp4'
};
},
onLoad() {
// 接收原生子窗体传来的数据的消息
uni.$on('popup-page', (data) => {
console.log(data);
switch(data.type){
case 'interactive':
uni.showModal({
title: '来自Popup的消息',
content: data.info
})
break;
default:
uni.showToast({
title: data.title,
})
break;
}
})
// 监听 drawer 消息
uni.$on('drawer-page', (data) => {
uni.showToast({
title: '点击了第' + data + '项',
icon:"none"
});
})
},
//移除监听
onUnload() {
uni.$off('popup-page')
uni.$off('drawer-page')
},
onReady() {
this.showVideo = true
},
methods: {
showPopup() {
// 向原生子窗体传递数据
uni.$emit('page-popup', {
title: '我是传递的内容'
});
const subNVue = uni.getSubNVueById('tSubNvue')
subNVue.show('slide-in-top', 250)
}
}
}
</script>
<style>
.content {
align-content: center;
height: 100%;
}
.example {
padding: 0 10px 10px
}
.example-title {
font-size: 14px;
line-height: 14px;
color: #777;
margin: 40px 2rpx;
position: relative
}
.example-title {
margin: 40rpx 0
}
.title {
font-size: 20px;
text-align: center;
color: #8f8f94;
}
</style>
原生子窗体的nvue页面代码(testSubNvue.nvue)
书写nvue页面需要注意一些样式和布局方面的:注意事项
<template>
<div class="wrapper">
<text class="title">{{title}}</text>
<scroller class="scroller">
<div>
<text class="content">{{content}}</text>
</div>
<div>
<text style="color: red; font-size: 30rpx;">以下为 Popup 内部滚动示例:</text>
</div>
<div class="cell" v-for="(item, index) in lists" @click="handle(item)" :key="index">
<text class="text">{{item}}</text>
</div>
</scroller>
<div class="message-wrapper">
<text class="send-message" @click="sendMessage">向页面发送消息</text>
</div>
</div>
</template>
<script>
export default {
data() {
return {
title: '',
content: '',
lists: [],
}
},
created() {
const that = this
for (let i = 1; i < 20; i++) {
this.lists.push('item' + i)
}
uni.$on('page-popup', (data) => {
console.log(data)
that.title = data.title
that.content = data.content
})
},
beforeDestroy() {
uni.$off('drawer-page')
},
methods: {
sendMessage() {
//获取当前子窗体的唯一id
const subNVue = uni.getCurrentSubNVue()
uni.$emit('popup-page', {
title: '已读完!',
})
}
}
}
</script>
<style>
.wrapper {
align-items: center;
flex-direction: column;
justify-content: center;
padding: 10rpx 15rpx;
background-color: #F4F5F6;
border-radius: 4rpx;
}
.title {
height: 100rpx;
line-height: 100rpx;
border-bottom-style: solid;
border-bottom-width: 1rpx;
border-bottom-color: #CBCBCB;
flex: 0;
font-size: 30rpx;
}
.scroller {
height: 400rpx;
padding: 8rpx 15rpx;
}
.content {
color: #555555;
font-size: 32rpx;
}
.message-wrapper {
flex: 0;
border-top-style: solid;
border-top-width: 1rpx;
border-top-color: #CBCBCB;
height: 80rpx;
align-items: flex-end;
}
.send-message {
font-size: 30rpx;
line-height: 80rpx;
color: #00CE47;
margin-left: 20rpx;
}
.cell {
margin: 10rpx;
padding: 20rpx 0;
top: 10rpx;
align-items: center;
justify-content: center;
border-radius: 10rpx;
background-color: #5989B9;
}
.text {
font-size: 30rpx;
text-align: center;
color: white;
}
</style>
数据打印截图