uniapp 混合nvue开发上下切换视频(弃用)

此文章存在挺多bug的,比如串音问题,黑屏问题,播放与暂停,占用内存过大,记录一下自己当前的开发思路

最初的构思开发:采用swiper上下切换

1.videoPlayer.nvue

<!-- videoPlayer.nvue -->
<template>
    <view class="videoPlayer">
        <video id="myVideo" class="video" :controls="false"
            :src="'https://xiaoshipin.com/sipin/'+src" ref="myVideo" :loop="true"
            :autoplay="false" @click="click" 
            object-fit="fill"
            :enable-progress-gesture="false"
            :show-fullscreen-btn="false"
            :show-play-btn="false"
            :show-center-play-btn="false"></video>
    </view>
</template>

<script>
    var timer = null 
    export default {
        props: ['src', 'state'],
        watch: {
            state: {
                immediate: true,
                handler() {
                    this.stateChange();
                }
            }
        },
        data() {
            return {
                play: false,
                dblClick: false,
            };
        },
        mounted() {

        },
        methods: {
            stateChange() {

                let videos = this.$refs['myVideo'];
                if (!!videos) {
                    let videoContext = videos;
                    switch (this.state) {
                        //视频播放
                        case 'play':
                            videoContext.play()
                            this.play = true
                            break;
                            //视频暂停
                        case 'pause':
                            videoContext.pause()
                            this.play = false
                            break;
                            //上下切换停止视频
                        case 'stop':
                            videoContext.pause(); //视频停止,从0开始
                            videoContext.seek(0);
                            this.play = false
                            break;
                        default:
                            break;
                    }
                }

            },
            click() {
                clearTimeout(timer)
                this.dblClick = !this.dblClick
                timer = setTimeout(() => {
                    if (this.dblClick) { //判断是单击 即为true
                        //单击
                        if (this.play === false) {
                            this.state = "play"
                        } else {
                            this.state = "pause"
                        }
                    } else {
                        //双击
                        this.$emit('dblClick') //向父组件传递一个事件
                    }
                    this.dblClick = false //点击后重置状态 重置为false
                }, 300)
            },
        }
    }
</script>

<style>
    .videoPlayer {
        flex: 1;
    }
    .video {
        flex: 1;
    }
</style>

2.subVideoList.nvue

<!-- subVideoList.nvue -->
<template>

    <view  class="page"> 
        <swiper  class="swiper" :circular="true" :vertical="true" @change="changeplay" >
            <swiper-item class="swiper-item" v-for="item in videos" :key="item.id">
                <view class="video" >
                    <video-player @dblClick='dblClick' :state="item.state" :src="item.src" >
                    </video-player> 
                </view>
            

            </swiper-item>
        </swiper>
    </view>
</template>

<script>
    import videoPlayer from './videoPlayer.nvue'
    export default {
        components: {
            videoPlayer
        },
        data() {
            return {
                videos: [],
                page: 0,
                page_old: 0,
            };
        },
        onLoad() {
            uni.$on('sendSubVideoList', (data) => {
                if (!!data) {
                    this.setState(this.page, 'play');
                } else {
                    this.setState(this.page, 'pause');
                }

            })
        },
        onReady() {
            this.videos = [{
                src: '1.mp4',
                state: 'pause'
            }, {
                src: '2.mp4',
                state: 'pause'
            }, {
                src: '3.mp4',
                state: 'pause'
            }, {
                src: '4.mp4',
                state: 'pause'
            }];
            this.$nextTick(() => {
                this.setState(this.page, 'play');
            })
        },
        methods: {
            dblClick() {
                //双击点赞  
            },
            changeplay(res) {
                this.page = res.detail.current
                this.setState(this.page_old, 'stop');
                this.setState(this.page, 'play');
                this.page_old = this.page;
            },
            setState(index, state_) {
                let item = this.videos[index];
                if (!!item) {
                    this.$set(this.videos, index, {
                        ...item,
                        state: state_
                    });
                }
            },
        }
    }
</script>

<style>
    .page {
        flex: 1;
    }
    .swiper {
        flex: 1;
    }
    .swiper-item {
        flex: 1;
        position: relative;
    }
    .video {
        flex: 1;
        /* #ifndef APP-PLUS */
        width: 100%;
        /* #endif */
    }
</style>

3.创建video.vue,修改pages.json

{
            "path": "pages/video/video",
            "style": {
                "navigationBarTitleText": "首页",
                "app-plus": {
                    "titleNView": false,
                    "subNVues": [{
                        "id": "subVideoList", // 唯一标识  
                        "path": "pages/video/subVideoList/subVideoList", // 页面路径  

                        "style": {
                            "position": "absolute",
                            "top": "0",
                            "left": "0",
                            "width": "100%",
                            "height": "100%",
                            "mask": "rgba(0,0,0,0)",
                            "background": "rgba(0,0,0,0)",
                            "zindex": 5
                        }
                    }]
                }
            }
        }

4.video.vue,使用subNVues显示原生子窗口

<template>
    <view>
<!-- 其他内容 -->
    </view>
</template>

<script>
    let subVideoList = null;
    export default {

        data() {
            return {

            };
        },

        onReady() {
            // #ifdef APP-PLUS
            //通过 ID 获取 subNVues 原生子窗体的实例
            subVideoList = uni.getSubNVueById('subVideoList');
            //#endif
            this.init();
            
        },
        onShow() {
            if (!!subVideoList) {
                subVideoList.show();
            }
//界面显示继续播放
            uni.$emit('sendSubVideoList', 1)
        },
        onHide() {
//界面隐藏停止播放
            uni.$emit('sendSubVideoList', 0)
        },
        methods: {
            init(){
                if (!!subVideoList) {
                    subVideoList.show();
                }
            }
        }
    }
</script>

<style>

</style>

5.完成,不流畅,初始化显示还存在空白!不知道是不是渲染问题!!

6.最后还是决定使用list+@appear来实现,思路:cell高度为屏幕高度,使用@appear监听当前视频下标,通过下标来停止与播放视频,最后subVideoList.nvue如下

<!-- subVideoList.nvue -->
<template>
    <view class="page">
        <list @loadmore="loadmore" :loadmoreoffset="loadmoreoffset" :show-scrollbar="false" :pagingEnabled="true">
            <cell v-for="(item, index) in videos" :key="index" :style="boxStyle" @appear="changeplay(index)">
                <video-player @dblClick='dblClick' :state="item.state" :src="item.src">
                </video-player>
            </cell>
        </list>
    </view>
</template>

<script>
    var deviceInfo = uni.getSystemInfoSync();
    import videoPlayer from './videoPlayer.nvue'
    export default {
        components: {
            videoPlayer
        },
        data() {
            return {
                loadmoreoffset: deviceInfo.windowHeight * 2, // 触发 loadmore 事件所需要的垂直偏移距离 加载到剩余2个的时候 继续加载
                boxStyle: {
                    width: '750rpx',
                    height: deviceInfo.windowHeight + 'px'
                },
                videos: [],
                page: 0,
                page_old: 0,
            };
        },
        onLoad() {
            uni.$on('sendSubVideoList', (data) => {
                if (!!data) {
                    this.setState(this.page, 'play');
                } else {
                    this.setState(this.page, 'pause');
                }

            })
        },
        onReady() {
            this.videos = [{
                src: '1.mp4',
                state: 'pause'
            }, {
                src: '2.mp4',
                state: 'pause'
            }, {
                src: '3.mp4',
                state: 'pause'
            }, {
                src: '4.mp4',
                state: 'pause'
            }];
            this.$nextTick(() => {
                this.setState(this.page, 'play');
            })
        },
        methods: {
            dblClick() {

            },
            loadMore(e) {
                //加载更多的视频
                this.videos.push({
                    src: 'new.mp4',
                    state: 'pause'
                })
                console.log('loadMore', e);
            },
            changeplay(index) {
                this.page = index
                this.setState(this.page_old, 'stop');
                this.setState(this.page, 'play');
                this.page_old = this.page;
            },
            setState(index, state_) {
                let item = this.videos[index];
                if (!!item) {
                    this.$set(this.videos, index, {
                        ...item,
                        state: state_
                    });
                }
            },
        }
    }
</script>

<style>
    .page {
        flex: 1;
    }
</style>

7.最终完成,上下切换流畅,测试100个视频也可以很流畅。

8.后期优化,数组动态加载与卸载,list组件缓存20个即可;点赞、评论、头像等使用cover-view覆盖在视频上面即可 ;page_old感觉很累赘,后期也删了

猜你喜欢

转载自blog.csdn.net/csdn_zuirenxiao/article/details/128588131