uniapp 微信小程序单个视频播放

uniapp 微信小程序单个视频播放

首先,我们先实现一个视频列表。

components\video-item.vue

1
2
3
4
5
6
<template>
<view class="container-video">
<view class="content">{{ item.content }}</view>
<video id="__video" :src="item.video_url" :__status="video_play_status" @play="handleVideoPlay"></video>
</view>
</template>

pages\index\index.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<template>
<view class="container">
<view v-if="list.length" class="list">
<video-item v-for="item in list" :key="item.id" :item="item"></video-item>
</view>
</view>
</template>

<script>
export default {
data() {
return {
list: [{
id: 1,
content: '测试1',
video_url: 'https://cdn.hongfs.cn/tmp/blog/video_20201129/1.mp4',
}, {
id: 2,
content: '测试2',
video_url: 'https://cdn.hongfs.cn/tmp/blog/video_20201129/2.mp4',
}, {
id: 3,
content: '测试3',
video_url: 'https://cdn.hongfs.cn/tmp/blog/video_20201129/3.mp4',
}, {
id: 4,
content: '测试4',
video_url: 'https://cdn.hongfs.cn/tmp/blog/video_20201129/4.mp4',
}, {
id: 5,
content: '测试5',
video_url: 'https://cdn.hongfs.cn/tmp/blog/video_20201129/5.mp4',
}, {
id: 6,
content: '测试6',
video_url: 'https://cdn.hongfs.cn/tmp/blog/video_20201129/6.mp4',
}],
}
},
}
</script>

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue'
import App from './App'

import video_item from './components/video-item.vue';

Vue.config.productionTip = false

Vue.component('video-item', video_item);

App.mpType = 'app'

const app = new Vue({
...App
});

app.$mount()

效果,可以看到默认情况下,点击其他视频之前视频在未播放结束情况下还是会继续播放。


实现单个视频播放的思路很简单,我们把可以唯一视频的 id 或者其他值存到 Vuex 里面,每次开始播放就存储这个标识值,监听到标识值和当前的不一样就停止播放。

store.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
state: {
// 当前视频 ID
current_video_id: null,
},
mutations: {
set_current_video_id (state, value) {
if(state.current_video_id !== value) {
state.current_video_id = value;
}
},
},
actions: {},
});

export default store;

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue'
import App from './App'
import store from './store';

import video_item from './components/video-item.vue';

Vue.config.productionTip = false

Vue.prototype.$store = store

Vue.component('video-item', video_item);

App.mpType = 'app'

const app = new Vue({
...App
})
app.$mount()

components\video-item.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<template>
<view class="container-video">
<view class="content">{{ item.content }}</view>
<video id="__video" :src="item.video_url" :__status="video_play_status" @play="handleVideoPlay"></video>
</view>
</template>

<script>
export default {
props: {
item: {
type: Object,
default: function() {
return {};
},
},
},
computed: {
// 获取视频播放状态,勿处理返回值
video_play_status () {
// 获取最新播放的视频 ID
const id = this.$store.state.current_video_id;

if (!id) return '';

if (id !== this.item.id) {
// ID 不一致则停止播放
const video = uni.createVideoContext('__video', this);
video.pause();
}

return '';
},
},
methods: {
handleVideoPlay () {
// 接受到视频播放就存储当前视频 ID
this.$store.commit('set_current_video_id', this.item.id);
},
},
}
</script>

最终效果。

往上