vue中使用vuex管理各種狀態


要使用vuex首先得安裝然后引入,在項目的src目錄下建立store文件夾,分別新建state,js,mutation.js,index.js.getter.js,actions.js

state.js,存儲了組件之間需要共享的變量:

import {
  playMode
} from '@/utils/config.js'
const state = {
  // 歌手信息:
  singer: {},
  // 是否正在播放音樂
  playing: false,
  // 播放器展開或者收起:
  fullScreen: false,
  // 播放的列表:
  playList: [],
  // 順序列表
  sequenceList: [],
  // 播放模式:
  mode: playMode.sequence,
  // 當前播放歌曲的索引:
  currentIndex: -1
}
export default state

 其中播放模式可以從外部引用,方便語義化的管理 config.js:

// 配置文件:

// 播放模式:
export const playMode = {
  // 順序播放:
  sequence: 0,
  // 循環播放:
  loop: 0,
  //   隨機播放:
  random: 2
}

 mutations.js定義了修改state的方法

const matutaions = {
  SET_SINGER(state, singer) {
    state.singer = singer
  },
  SET_PLAYING_STATE(state, flag) {
    state.playing = flag
  },
  SET_FULL_SCREEN(state, flag) {
    state.fullScreen = flag
  },
  SET_PLAYLIST(state, list) {
    state.playList = list
  },
  SET_SEQUENCE_LIST(state, list) {
    state.sequenceList = list
  },
  SET_PLAY_MODE(state, mode) {
    state.mode = mode
  },
  SET_CURRENT_INDEX(state, index) {
    state.currentIndex = index
  }
}
export default matutaions

 getters.js類似於組件中computed,可以對mutations的數據再處理,也可以直接拿到state的數據

// 重新包裝一下方便直接從組件中拿到數據
export const singer = state => state.singer

export const playing = state => state.playing

export const fullScreen = state => state.fullScreen

export const playList = state => state.playList

export const sequenceList = state => state.sequenceList

export const mode = state => state.mode

export const currentIndex = state => state.currentIndex

// 獲取當前播放歌曲
export const currentSong = (state) => {
  return state.playList[state.currentIndex] || {}
}

actions可以同時提交多個mutations,一些異步方法也可以在這里使用

// 同時操縱多個mutation可以使用actions;

// 封裝多個mutations:
export const selectPlay = function ({
  commit,
  state
}, {
  list,
  index
}) {
  console.log(state);

  commit('SET_SEQUENCE_LIST', list)
  commit('SET_PLAYLIST', list)
  commit('SET_CURRENT_INDEX', index)
  commit('SET_FULL_SCREEN', true)
  commit('SET_PLAYING_STATE', true)
}

在歌手列表頁點擊歌手之后需要跳轉到歌手詳情,同時需要把歌手信息傳遞進去,方法一可以用參數傳遞的方式,方法二傳遞歌手ID直接再歌手詳情頁面,重新獲取數據,方法三可以直接使用 vuex

在這里使用vuex,因為要改變state,所以引入 mapMutations,

先引入mapMutations

import { mapMutations } from "vuex";

methods中展開mutations,SET_SINGER為mutations中的方法名

    ...mapMutations({
      setSinger: "SET_SINGER"
    })

 點擊事件傳遞item給mutation 

this.setSinger(item); 傳遞item

    Todetail(item) {
      // console.log(item);
      this.$router.push({
        path: `/singer/${item.id}`
      });
      // 實際調用了this.$store.commit('setSinger',item)....
      this.setSinger(item);
    },  

 歌手詳情頁的頭部需要用到vuex中保存的歌手信息

 

 

 在singer-detail組件中的computed方法中定義getters:

import { mapGetters } from "vuex";

 

    ...mapGetters(["singer"]),
    title() {
      return this.singer.name;
    },
    bgImage() {
      return this.singer.avatar;
    }

 因為這個音樂列表在其他歌單列表也會用到,所以抽象成組件,把參數作為props傳遞進去

前面因為傳遞了歌手id,所以可以根據這個id去獲取該歌手的top50首歌

      const { artist, hotSongs } = await getSingerMusic(this.singer.id);
      // 歌手信息
      this.artistInfo = artist;
      // 熱門歌曲
      this.hotSongs = hotSongs;

 解構出的artist保存着歌手更全的信息

 

 

 

 

 

    

hotSongs保存着那50首歌曲的信息

  

 

 

   這同樣是沒法用的,所以也需要一個格式化函數獲取需要的數據

需要的是歌曲id,歌單id,唱這首歌的全部歌手,姓名(主唱),專輯,播放時長,圖片

在common文件夾中新建一個song.js

歌曲的播放地址需要通過id發送請求再獲得

//獲取歌曲播放地址
export const getsongUrl = p => get(`/song/url`, p)

song.js中引入

import {
  getsongUrl,
} from "@/request/api.js";

歌手可能有多個所以准備一個轉換函數把數組轉換成‘/’分割的字符串

function filterSinger(singer) {
  let ret = [];
  if (!singer) {
    return ''
  }
  singer.forEach((s) => {
    ret.push(s.name)
  })
  return ret.join('/')
}  

定義一個構造函數

export default class Song {
  constructor({
    id,
    mid,
    singer,
    name,
    album,
    duration,
    image,

  }) {
    this.id = id;
    this.mid = mid;
    this.singer = singer;
    this.name = name;
    this.album = album;
    this.duration = duration;
    this.image = image;
    getsongUrl({
      id: this.id
    }).then(res => {
      // console.log(res.data[0]);
      this.url = res.data[0].url
    })
  }
}

 導出一個歌曲生成的構造函數,參數是全部數據的data,根據參數返回需要的結果

export function createSong(musicData) {
  return new Song({
    id: musicData.id,
    mid: musicData.al.id,
    singer: filterSinger(musicData.ar),
    duration: musicData.duration ? musicData.duration : musicData.dt ? musicData.dt : '',
    name: musicData.name,
    album: musicData.al.name,
    image: musicData.al.picUrl + '?param=300y300',
    url: musicData.id
  })
}  

回到singer-detail,引入這個函數

import { createSong } from "@/common/song";

 定義格式化函數,在執行函數時確保id存在

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

使用該函數

      // 熱門歌曲
      this.songs = this._normalizeSongs(hotSongs);
      console.log(this.songs);

 可以看到那50首歌都格式化好了

 

 

 

  最后把數據給子組件就好了

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

  

 

 

 

 

  

  

  

 

  

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM