在我的上一篇博客(http://t.csdnimg.cn/LAQ4w)中,我们封装一个类似于微信消息播放的组件,但是会遇到一个问题,因为每一个实例化出来的组件都是单独的,里面的audio也是单独的,在我们点击另外一个组件播放声音时,我们会发现上一次播放的声音依旧在播放,导致两个声音重叠了,那我们应该怎么解决这个问题呢?
此时就要用到ref作为元素的Attribute,给每一个声音播放组件绑定一个相同的ref,这个我们可以拿到所有的声音播放器的实例;详情查询Vue3官网:https://cn.vuejs.org/api/built-in-special-attributes.html#refhttps://cn.vuejs.org/api/built-in-special-attributes.html#ref
另外我们还使用到另一个api——$el,详情请查看Vue3官网:
这个属性可以让我们获取到ref定义的实例的真实dom元素
我们在点击元素时,把鼠标点击的event事件传递过来
<VoicePlayback
ref="voiceRef"
:isSent="false"
iconColor="#ffffff"
backgroundColor="rgba(255 255 255 / 20%)"
:smallSize="5"
:middleSize="16"
:largeSize="28"
:duration="30"
audioSrc="http://11111.mp3"
@click.stop="(event:Event)=>{
handlePlayAudio(event)
}"
/>
在这里的event中有两个属性:
event.target:可以得到当前鼠标点击作用于哪个dom上面,它是具体到这个组件的子dom;
event.currentTarget:得到当前点击事件绑定的dom元素;
所以这里我们需要使用event.currentTarget刚好的找到当前声音播发器的组件,voiceRef.value是一个数组我们需要遍历他通过$el属性来找到当前鼠标点击的dom元素和哪一个ref实例.$el得到的dom相同,记录这个组件实例,在下一次播放声音时,停止上一次的声音播放。
// 点击播放器时,暂停上一次的声音播放
const handlePlayAudio = (event: Event) => {
// 判断当前点击的声音播放的组件是不是与上次相同,如果相同,则return,不执行下面的代码
if (lastVoiceRef.value && lastVoiceRef.value.$el == event.currentTarget) {
return;
} else {
// 如果上一次的声音播放的组件存在,先暂停他的播放
lastVoiceRef.value && lastVoiceRef.value.pauseVoice();
}
for (let i of voiceRef.value) {
// 遍历所有的voiceRef绑定的实例,找到当前鼠标点击事件绑定的元素event.currentTarget在ref绑定的元素数组中的实例,赋给上一次的声音播放实例
if (event.currentTarget == i.$el) {
lastVoiceRef.value = i;
}
}
};