This is the sixth day of my participation in the November Gwen Challenge. See details: The Last Gwen Challenge 2021. Recently received a task arrangement, is about WeChat small programs, have a list of articles, types have a graphic and video, and video in the list can be directly playback, existing functionality is already written, now have to deal with the optimization problem, is to play the video there is only one, that is in a video, click the play Other videos that are playing should be paused.
It’s easy to use the Api createVideoContext and Pause ()
The person who should develop this function should add it in minutes, judging the current page cycle
When I took a look at the code, I realized that it was not as simple as I had imagined. The component nested multiple layers
-
The component A(list) is introduced in pageA (main page) to pass in (props) the list of list data
-
Component A introduces component B and loops in the detail data from component B according to the list
-
Receive detail in component B graphics and video for rendering
In fixed on the basis of the original code optimization to have certain difficulty, although the trouble, but also can deal with, through the components of the communication between the father children can solve, but then consider that this video optimization requirements, also involves the details page, and part of the page, and so on, if each write can’t end, then, If you want to separate the video playback function into a component videoHandle, you just need to replace all the video labels with videoHandle, once and for all.
The next step was to figure out how to handle the communication between all the videoHandle components, eventually adopting the publish-subscribe model
The project is based on UNIAPP and the page files follow the Vue Single File Component (SFC) specification
Handwritten publishing subscription
Create a myevent. Js
Export default class myevent{// Store event queue constructor(){this. MSG = {}} /** * SUBSCRIBE event * @param {*} key Event identifier * @param {*} fn event method */ subscribe(key, fn){... } /** * publish all events in the queue, notify all subscribers */ publish() {... * @param {*} key * @param {*} fn */ remove(key, fn){... } /** * get the number of queues */ getQueue(key){... }}Copy the code
Subscribe to the event
Subscribe (key, fn){// If the callback function is not a method, return if(typeof fn! // If this queue does not exist, create a new if(! This.msg [key]) this.msg[key] = [] // Add the event to the message queue this.msg[key].push(fn)}Copy the code
Publish notifications to subscribers
Arguments are used to facilitate passing in and receiving multiple arguments
arguments
The publish () {/ / get the key parameters, and remove the first parameter let key = Array. The prototype. The shift. The call (the arguments) let FNS. = this MSG (key) / / event is null is returned if (! fns||! Fn. Length) return fn. ForEach (res => {// execute the event and pass in the arguments res.apply(null, arguments)})}Copy the code
Remove event
Remove (key, fn) {let FNS = this. MSG [key] // Return if(! fns || ! Fn. Length) return if(! Fn) {delete this. MSG [key]}else {// loop delete the specified event for(let I =0; i<fns.length; i++){ let item = fns[i] if(item === fn || item.fn === fn) { fns.splice(i,1) break } } } }Copy the code
Gets the number of current queues
To know the number of events in the queue, you can call this method to see
getQueue(key){ if(! this.msg[key]) return undefined return this.msg[key].length }Copy the code
The introduction of the main. Js
. import myevent from '@/common/utils/myevent' Vue.prototype.$event = new myevent() ...Copy the code
Video component videoHandle
When you create a component, generate a unique GUID, subscribe to the eventSuspend message, and bind to the event eventSuspend to receive the message. When a video is played, publish the message with this GUID and notify all subscribers (all videoHandle, including this component). After receiving the notification, The guID handles the pause action of the current video
The specific code is as follows
<template> <video class="my-video" :id='id' :src="url" object-fit="cover" @error="videoErrorCallback" @play="playing" controls > </video> </template> <script> export default { props: { url: { type: String, default: '', }, }, data() { return { id:'', url: "'}}, Created () {this.id = this.$u.uid () // Subscribe to eventSuspend message and bind this.eventSuspend() this.$event.subscribe('eventSuspend', this.receiveSuspend) }, methods: { videoErrorCallback (e) { console.log('videoErrorCallback') console.log(e) }, // Receive message notification receiveSuspend(id){console.log(' suspend playback ', this.id, id) // Stop playback if the received ID does not match the video ID. {this. = = this. Id) pause ()}}, / / play triggered when playing () {/ / news, $event.publish('eventSuspend', this.id)}, // Pause (){wx.createVideoContext(this.id, Destroy () {this.$event.remove('eventSuspend', this.eventsuspend)},}; </script> <style scoped lang="scss"> .my-video{ width: 100%; height: 100%; } </style>Copy the code