uni-app之實現層級覆蓋(app端覆蓋原生組件)的問題

  1. 具體問題:拓展組件uni-popup無法正常覆蓋video組件
  2. 問題描述:在APP端,如果頁面中使用了video組件,則拓展組件uni-popup(里面包括一個view組件,view下是個image組件)不能正常覆蓋原生組件video。
    示例:主要有一個video原生組件、一個image原生組件和一個uni-popup拓展組件
<template>
    <view>
        <view class="flex-sub margin-right-xs" style="height: 95%;">
            <video style="width: 100%;height: 100%;" id="myVideo" src="http://img.cdn.qiniu.dcloud.net.cn/wap2appvsnative.mp4" controls></video>
        </view>
        
        <view class="flex-sub margin-right-xs" style="align-self: center;" @tap="showBigImage">
            <image style="width: 150upx;height: 150upx;" src="https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg" mode="aspectFit"></image>
        </view>

        <uni-popup class="uni-bg-white" :show="type === 'middle'" position="middle" mode="fixed" @hidePopup="togglePopup('')">
            <view class="uni-bg-white" style="width:500upx;height:300upx;">
                <image style="width: 100%;height: 100%;" src="https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg" mode="aspectFit"></image>
            </view>
        </uni-popup>
    </view>
</template>

<script>
import uniPopup from "@/components/uni-popup/uni-popup.vue";
var _self;
export default {
    components: {
        uniPopup,
    },
    data() {
        return {
            type:"",
        }
    },
    methods: {
        showBigImage:function(){
            _self.type = "middle";
        },
        togglePopup(type) {
            _self.type = type;
        }
    },
    onLoad:function(){
        _self = this;
    }
}
</script>
<style>
.cover-img{
    position: fixed;
    z-index: 999;
    background-color: #ffffff;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 10upx;
    padding: 30upx;
}
</style>

h5端可正常覆蓋:


h5端可正常覆蓋.png

app端不能正常覆蓋:


app端不能正常覆蓋.png
  1. 分析:<video/> 組件在非H5端是客戶端創(chuàng)建的原生組件,它的層級是最高的,高于普通前端組件,不能通過 z-index 控制層級??墒褂?cover-viewcover-image覆蓋在上面,也可通過plus.nativeObj.view或原生子窗體subNVue等方式來實現。
  • App端 cover-view、cover-image 中不支持嵌套其它組件。
  • App端暫不支持 cover-view、cover-image 組件之間的嵌套。
  • App端cover-view可覆蓋的原生組件有限制,目前僅包括:video、map
  • App端還可以使用更強大的plus.nativeObj.view繪制原生內容,參考:uni-app中使用5+界面控件、plus.nativeObj.view規(guī)范
  • App端還提供了更靈活和強大的subNvue,比cover-view和plus.nativeObj.view都更強大,參考原生子窗體subNvue
  • 其他小程序平臺下,可以使用條件編譯,完全按照其規(guī)范開發(fā)。
  • 在 video 組件中使用時,不支持在全屏模式下使用cover-view。
  • 支付寶小程序中 cover-view 不支持嵌套。

拓展:微信基礎庫 2.4.0 起已支持 video 組件的同層渲染,也就是video在非全屏時,可以被前端元素通過調節(jié)z-index來遮擋,但video全屏時,仍需要cover-view覆蓋。
(1) 使用cover-image替代uni-popup:一方面程序報錯,一方面也不符合操作需求,棄用

<cover-image class="cover-img" style="width:500upx;height:300upx;" src="https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg" mode="aspectFit"></cover-image>

cover-image在app端報錯.png

(2) 使用plus.nativeObj.view:雖然更靈活,但易用性比較差、沒有動畫、不支持內部內容滾動
(3) 原生子窗體subNvue
說明:subNVues 是 vue 頁面的原生子窗體。用于解決 vue 頁面中的層級覆蓋和原生界面靈活自定義用的。它不是全屏頁面,也不是組件,就是一個原生子窗體。它是一個 nvue 頁面,使用 weex 引擎渲染,提供了比 cover-view、plus.nativeObj.view 更強大的原生排版能力,方便自定義原生導航或覆蓋原生地圖、視頻等。
注意:原生子窗體subNvue替代了原生增強提示框插件,避免原生插件麻煩的打包流程。

  • pages.json
,{
            "path" : "pages/ipms/miaoyou/home/home",
            "style" : {
                "app-plus": {  
                    "titleNView": false,  //不啟用系統(tǒng)導航
                    "subNVues":[{  
                        "id": "popup", // 唯一標識  
                        "path": "pages/ipms/miaoyou/home/subNVue/popup", // 頁面路徑  
                        "type": "popup",  //原生子窗口內置樣式,可取值:'popup',彈出層;"navigationBar",導航欄
                        "style": {  
                            "margin": "auto",
                            "width": "50%",
                            "height": "400upx"  
                        }  
                    }]  
                } 
            }
            
        }
  • home.vue 部分代碼
<template>
    <view class="uni-flex uni-row" style="width: 100%;height: 100%;">
        <view style="width: 50%;height: 98%;">
            <video style="width: 100%;height: 100%;" id="myVideo" src="http://img.cdn.qiniu.dcloud.net.cn/wap2appvsnative.mp4" controls></video>
        </view>
        
        <view style="width: 50%;height: 98%;" @tap="showBigImage">
            <image style="width: 100%;height: 100%;" src="https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg" mode="aspectFit"></image>
        </view>
        
        <uni-popup class="uni-bg-white" :show="type === 'middle'" position="middle" mode="fixed" @hidePopup="togglePopup('')">
            <view class="uni-bg-white" style="width:500upx;height:300upx;">
                <image style="width: 100%;height: 100%;" src="https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg" mode="aspectFit"></image>
            </view>
        </uni-popup>
    </view>
</template>

<script>
import uniPopup from "@/components/uni-popup/uni-popup.vue";
var _self;
export default {
    components: {
        uniPopup,
    },
    data() {
        return {
            type:"",
        }
    },
    methods: {

        showBigImage:function(){
            // #ifdef H5
            _self.type = "middle";
            // #endif
                
            // #ifdef APP-PLUS
            _self.showPopup();
            // #endif
            
        },
        showPopup() {
            uni.$emit('page-popup', {// 向 popup 傳遞消息
                imageUl: 'https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg',
                videoUrl:'http://img.cdn.qiniu.dcloud.net.cn/wap2appvsnative.mp4'
            });
            const subNVue = uni.getSubNVueById('popup');// 通過 id 獲取 nvue 子窗體 
            subNVue.show('slide-in-top', 250);// 打開 nvue 子窗體
        },
        togglePopup(type) {
            _self.type = type;
        }
    },
    onLoad:function(){
        _self = this;
    }
}
</script>
<style>
.cover-img{
    position: fixed;
    z-index: 999;
    background-color: #ffffff;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 10upx;
    padding: 30upx;
}
</style>


  • popup.nvue
<template>
    <div style="text-align: center;vertical-align: middle;">
        <image style="vertical-align: middle;" :src="imageUl" mode="aspectFit"></image>
        <!-- <video style="vertical-align: middle;" :src="videoUrl" controls></video> -->
    </div>
</template>

<script>
export default {
    data() {
        return {
            imageUl: '',
            videoUrl:''
        }
    },
    created() {
        const vm = this;
        uni.$on('page-popup', (data) => {
            vm.imageUl = data.imageUl;
            vm.videoUrl = data.videoUrl;
        })
    },
    beforeDestroy() {
        uni.$off('page-popup')
    },
}
</script>

<style>

</style>

可能遇到的問題

  • 獲取到原生子窗體實例為null:查看id是否匹配正確
  • 實例方法未定義:編譯模式查看是否為自定義編譯模式


    app端最終效果.png

參考原生組件說明

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容