VUE移动端音乐APP学习【十七】:歌单详情页组件开发

歌单详情页基础开发

歌单详情页和歌曲列表页面是非常类似的,只是数据上的不同。以下是这个组件的基本结构:可以看到和我们的singer-detail一样都有transition动画以及使用了music-list组件,接下来就是想办法把music-list数据传进去。

<template>
  <transition>
    <music-list></music-list>
  </transition>
</template>

<script>
import MusicList from '../music-list/music-list';

export default {
  name: 'disc',
  components: {
    MusicList,
  },
};
</script>

<style lang="scss" scoped>
  .slide-enter-active,
  .slide-leave-active {
    transition: all 0.3s;
  }

  .slide-enter,
  .slide-leave-to {
    transform: translate3d(100%, 0, 0);
  }
</style>

这个组件首先是个二级路由,需要先去router下设置成二级路由。

 {
    path: '/recommend',
    name: 'Recommend',
    component: Recommend,
    children: [{
      path: ':id',
      component: Disc,
    }],
  }

然后回到recommend添加<router-view>,并且给歌单列表添加点击事件,就可以实现路由跳转

 <div class="recommend" ref="recommend">
    <scroll>
    ....
        <li @click="selectItem(item)" v-for="item in discList" class="item" :key="item.id">
    ....
    </scroll>
 <router-view></router-view>
</div>
    
selectItem(item) {
      this.$router.push({
        path: `/recommend/${item.dissid}`,
      });
    },

通过vuex把歌单数据传过去,首先在state下面定义歌单的对象,其次添加mutation-types,利用它在mutations添加更改函数

//state.js
const state = {
  singer: {},
  // 播放状态默认为暂停
  playing: false,
  // 播放器默认为收起
  fullScreen: false,
  // 播放列表
  playlist: [],
  // 顺序列表
  sequenceList: [],
  // 播放模式默认为顺序播放
  mode: playMode.sequence,
  // 当前播放索引
  currentIndex: -1,
  // 歌单对象
  disc: {},
};

//mutation-types.js
export const SET_DISC = 'SET_DISC';

//mutations.js
 [types.SET_DISC](state, disc) {
    state.disc = disc;
  },

最后设置它的getters方法

export const disc = (state) => state.disc;

通过mustation去设置disc,有了mutation之后就可以在刚才的点击方法里调用更改state里的disc

//recommend.vue
import { mapMutations } from 'vuex';

...mapMutations({
    setDisc: 'SET_DISC',
  }),

 selectItem(item) {
      this.$router.push({
        path: `/recommend/${item.id}`,
      });
      this.setDisc(item);
    },

disc.vue就可以接收使用这个数据

<template>
  <transition>
    <music-list :title="title" :bg-image="bgImage"></music-list>
  </transition>
</template>

import { mapGetters } from 'vuex';

computed: {
    title() {
      return this.disc.name;
    },
    bgImage() {
      return this.disc.picUrl;
    },
    ...mapGetters([
      'disc',
    ]),
  },

抓取歌单详情数据 

在recommend.js下设置接口

export function getSongList(id) {
  return axios.get(`api/playlist/detail?id=${id}`);
}

在disc.vue调用api发起请求,获取数据

import { ERR_OK } from '../../api/config';

created() {
    this._getSongList();
  },
  methods: {
    _getSongList() {
      getSongList(this.disc.id).then((res) => {
        if (res.code === ERR_OK) {
          console.log(res.playlist.tracks);
        }
      });
    },
  },

歌单详情数据应用

通过createSong方法处理歌单数据将歌曲传入music-list,同时可以看到组件复用的效果

<template>
  <transition>
    <music-list :title="title" :bg-image="bgImage" :songs="songs"></music-list>
  </transition>
</template>

import { createSong } from '../../common/js/song';

data() {
    return {
      songs: [],
    };
  },



 _normalizeSongs(list) {
      let ret = [];
      list.forEach((musicData) => {
        if (musicData.id && musicData.al.id) {
          ret.push(createSong(musicData));
        }
      });
      console.log(ret);
      return ret;
    },
  },


最后需要处理个小问题,当刷新页面的时候,数据就丢失了,解决方法和歌手详情页的逻辑一样,在_getSongList方法添加判断如果获取不到歌单id就回退上一个路由推荐页面

 _getSongList() {
      if (!this.disc.id) {
        this.$router.push('/recommend');
        return;
      }
      getSongList(this.disc.id).then((res) => {
        if (res.code === ERR_OK) {
          console.log(res.playlist.tracks);
          this.songs = this._normalizeSongs(res.playlist.tracks);
        }
      });
    },
原文地址:https://www.cnblogs.com/Small-Windmill/p/14753295.html