音乐播放器笔记

210 阅读4分钟

v-for内的传值

  • 给v-for内的对象绑定事件,只对某个对象触发事件,是需要传值的,通过v-for内的属性,触发事件的同时会将对应的属性传递给方法来接收

    这里通过 @click='selectedSong(index)' 向selectedSong方法传当前被点击的li的index值

  • 方法内通过 this.selectSong = index 将被点击的对象的index值赋值给唯一的属性selectSong,通过这个属性的值来判断到底是点击了哪个,来操作数组对应index的对象或属性

  • 这里就是通过传出的index通过 :class='{active:index == selectSong}' 将selectSong的值赋值给index,来为被点击的对象添加 active 类

  • v-for的对象内嵌套事件,也是需要通过传值来判断事件的目标,传入不同的属性,处理方式就不一样,这里传入的song,相当于给事件提供了this指向,来给this下的collect属性通过isCollect方法来赋值

    另一个方法是传入 index

    <div class="btn">
        <img @click.stop='isCollect(index)' v-if='song.collect' src="img/collected.svg" alt="">
        <img @click.stop='isCollect(index)' v-else src="img/collect.svg" alt="">
        <img src="img/play.svg" alt="">
    </div>
    
    isCollect(index) {
        this.musicList[index].collect = !this.musicList[index].collect;
    }
    

    这个方法是点击后,通过传出的 index 值找到对应数组内的对象,再对对象内的属性赋值

  • v-for 内的对象嵌套 v-if 获取this指向也是通过传值来实现的,这里传入了song,为了让if显示else隐藏后,还可以触发事件,需要两个元素都绑定上点击事件,这个方法适用于不需要频繁切换的内容

    另一个方法就是用 v-show :

    <div @click.stop='isCollect(index)'>
       <img v-show='song.collect' src="img/collected.svg" alt="">
       <img v-show='!song.collect' src="img/collect.svg" alt="">
    </div>
    

    给父元素添加点击事件,然后内部的元素均添加 v-show ,不同的是,在其中一个的属性前方加 ! 取非,以此来实现toggle

<li class="song" v-for='(song,index) in musicList' :key='index'
    :class='{active:index == selectSong}' @click="selectedSong(index)">
    <div>
        <p class="index">{{index+1}}</p>
        <img class="song-cover" :src="song.cover" alt="">
        <div class="title">
            <h5>{{song.title}}</h5>
            <h6>{{song.singer}}</h6>
        </div>
    </div>
    <div class="btn">
        <img @click.stop='isCollect(song)' v-if='song.collect' src="img/collected.svg"
             alt="">
        <img @click.stop='isCollect(song)' v-else src="img/collect.svg" alt="">
        <img src="img/play.svg" alt="">
    </div>
</li>
data:{
    selectSong: -1,//通过设置index初始值为-1,来让默认选中的元素为空
    playerstatus: false,
    playingInfo: {
    	title: '暂无播放',
        singer: '&nbsp',//带有标签或为html内容时使用v-html插值
        cover: 'img/cover/blank.jpg',
        src: '',
        ...
                },
    musicList:[
        {
            ...
            cover: 'img/cover/xxx.jpg',
            src: 'music/xxx.mp3',
            collect: false,
            ...
        },
    ]
},
methords:{
	selectedSong(index) {
    	this.selectSong = index;
    },
    isCollect(song) {
    	song.collect = !song.collect;//通过取反,来实现toggle
    }
},
watch: {
    selectSong: function (newV) {
        this.playingInfo = this.musicList[newV];
        this.playerstatus = true;
    },
}
  • 通过侦听 selectSongindex 值的变化做出反应,将 index 对应的数组中的对象全部属性覆盖给播放器对象属性

列表的循环

数组的长度为0-14 index 的15 length 个对象,所以需要 -1length = index

<div class="btn">
    <img @click='prevBtn' src="img/next.svg" alt="">
    <div @click='stopMusic'>
        <img v-show='playerstatus' src='img/puased.svg' alt="">
        <img v-show='!playerstatus' src='img/play.svg' alt="">
    </div>
    <img @click='nextBtn' src="img/next.svg" alt="">
</div>
data:{
    playerstatus: false,
},
methords:{
    stopMusic() {
        this.playingInfo = this.playerInitial;//把播放器初始化的属性值赋值给播放器
        this.playerstatus = false;
    },
    prevBtn() {
    	if (this.selectSong > 0) {//判断当前选中的对象index是否等于0
        	this.selectSong--;//大于0,就表示没有选中第一个,可以一直-1
        } else {
            this.selectSong = this.musicList.length - 1;//等于0的时候让值等于数组最后一个对象的index
        }
    },
    nextBtn() {
        if (this.selectSong < this.musicList.length - 1) {//判断当前选中的对象index是否等于数组最后一个对象的index
            this.selectSong++;//小于的话,表示没有选中最后一个,可以一直+1
        } else {
            this.selectSong = 0;//等于数组长度时,再次点击,让index=0,选中第一个
        }
    }
}

对歌词添加注释

对歌词统一添加一段注释,if用来判断lrc是否为初始的空值,控制的话为false则什么都不做,播放器的lrc属性值被更改后,有了值则变为true,执行if内的处理,添加注释,dom内插值时插入计算方法

watchthis.playingInfo.lrc 覆盖的话会导致多次添加的问题,用 computed ,少写一个添加注释后的属性,更方便

computeds:{
    lrcNote() {
        if (this.playingInfo.lrc) {
            return `<span>请手动滚动歌词</span><br>${this.playingInfo.lrc}`
        }
    },
}