【音樂App】—— Vue-music 項目學習筆記:用戶個人中心開發


前言:以下內容均為學習慕課網高級實戰課程的實踐爬坑筆記。

項目github地址:https://github.com/66Web/ljq_vue_music,歡迎Star。


歌曲列表 收藏歌曲
一、用戶個人中心開發

       基礎功能開發

  • 設置路由跳轉
  1. 在components->user-center目錄下:創建user-center.vue
  2. router->index.js中配置路由:
    { path: '/user', component: UserCenter }
  3. m-header.vue中通過<router-link>實現跳轉
    <router-link tp="/user" class="mine" tag="div">
        <i class="icon-mine"></i>
    </router-link>
  • 應用Switches組件
  1. 引用注冊並使用
    <switches @switch="switchItem" :switches="switches" :currentIndex="currentIndex"></switches>
  2. 定義data數據綁定
    data() { return { currentIndex: 0, switches: [ {name: '我喜歡的'}, {name: '最近聽的'} ] } }
  3. 定義方法將獲得的index賦值給currentIndex
    switchItem(index) { this.currentIndex = index }
  • 返回上一級路由
  1. 給按鈕添加點擊事件
    @click="back"
  2. 定義方法通過router.back返回
    back(){ this.$router.back() //回退到上一級路由
    }

       收藏列表開發

  • Vuex數據配置
  1. states.js中:添加數據
    favoriteList: []
  2. mutation-types.js中:定義事件類型常量
    export const SET_FAVORITE_LIST = 'SET_FAVORITE_LIST'
  3. mutations.js中:定義修改方法
    [types.SET_FAVORITE_LIST](state, list){ state.favoriteList = list }
  4. getters.js中:設置數據映射
    export const favoriteList = state => state.favoriteList
  • catch.js中操作storage
  1. 定義本地緩存的Key和最大存儲歌曲值
    const FAVORITE_KEY = '_favorite_' const FAVORITE_MAX_LENGTH = 200
  2. 保存歌曲到本地緩存
    export function saveFavorite(song) { let songs = storage.get(FAVORITE_KEY, []) insertArray(songs, song, (item) => { return song.id === item.id }, FAVORITE_MAX_LENGTH) storage.set(FAVORITE_KEY, songs) return songs }
  3. 從本地緩存中刪除歌曲
    export function deleteFavorite(song) { let songs = storage.get(FAVORITE_KEY, []) deleteFromArray(songs, (item) => { return song.id === item.id }) storage.set(FAVORITE_KEY, songs) return songs }
  4. 從本地緩存中獲取全部歌曲
    export function loadFavorite() { return storage.get(FAVORITE_KEY, []) }
  • actions.js中:封裝方法
  1. 同時保存到Vuex和本地緩存
    export const saveFavoriteList = function ({commit}, song) { commit(types.SET_FAVORITE_LIST, saveFavorite(song)) }
  2. 同時從Vuex和本地緩存刪除
    export const deleteFavoriteList = function ({commit}, song) { commit(types.SET_FAVORITE_LIST, deleteFavorite(song)) }
  • states.js中修改初始數據為本地緩存數據
    favoriteList: loadFavorite()
  • player.vue中修改按鈕,動態綁定class,監聽點擊事件
    <i class="icon" @click="toggleFavorite(currentSong)" :class="getFavoriteIcon(currentSong)">
  • mixin.js中在playerMixin中添加收藏歌曲需要的共享邏輯
  1. 通過mapGetters獲得已收藏的歌曲數據:'favoriteList'
  2. 抽象出一個方法判斷所選歌曲是否在已收藏的歌曲數據中
    isFavorite(song){ const index = this.favoriteList.findIndex((item) => { return item.id === song.id }) return index > -1 //如果index > -1 isFavorite 返回true
    }
  3. 定義方法依據所選歌曲是否為已收藏的歌曲,取反改變icon樣式
    getFavoriteIcon(song){ if(this.isFavorite(song)){ return 'icon-favorite' } return 'icon-not-favorite' }
  4. 定義方法調用通過mapActions引用的action,同上取反進行保存或刪除
    toggleFavorite(song){ if(this.isFavorite(song)){ this.deleteFavoriteList(song) }else{ this.saveFavoriteList(song) } }
  • playlist.vue中添加數據映射和點擊事件
    <span class="like" @click.stop="toggleFavorite(item)">
        <i :class="getFavoriteIcon(item)"></i>
    </span>
  • usercenter.vue中渲染收藏列表和播放歷史列表
  1. 布局DOM: 同add-song.vue
    <scroll ref="favoriteList" class="list-scroll" v-if="currentIndex===0" :data="favoriteList">
            <div class="list-inner">
                <song-list :songs="favoriteList" @select="selectSong"></song-list>
            </div>
    </scroll>
    <scroll ref="playList" class="list-scroll" v-if="currentIndex===1" :data="playHistory">
            <div class="list-inner">
                <song-list :songs="playHistory" @select="selectSong"></song-list>
            </div>
    </scroll>
  2. 通過mapGetters獲取收藏歌曲數據和播放歷史數據
    computed: {
       ...mapGetters([
          'favoriteList',
          'playHistory'
      ])
    }
  3. 定義方法,調用通過mapActions獲取到的insertSong方法,將song實例化之后插入
    selectSong(song) {
       this.insertSong(new Song(song)) 
    },
    ...mapActions([
       'insertSong'
    ])

       剩余功能開發

  • 隨機播放全部功能實現
  1. 給按鈕添加點擊事件,通過mapActions獲取到randomPlay方法
    <div ref="playBtn" class="play-btn" @click="random">
  2. 定義方法,判斷currentIndex獲取對應list,通過實例化處理傳入action
    random(){ let list = this.currentIndex === 0 ? this.favoriteList : this.playHistory //這時list還不是實例,需要遍歷list進行實例化
        list = list.map((song) => { return new Song(song) }) this.randomPlay({ list }) }
  • 播放器底部自適應
    import {playlistMixin} from '@/common/js/mixin' mixins:[playlistMixin], handlePlaylist(playlist){ const bottom = playlist.length > 0 ? '60px' : ''
        this.$refs.listWrapper.style.bottom = bottom //判斷列表DOM存在后再執行refresh
        this.$refs.favoriteList && this.$refs.favoriteList.refresh() this.$refs.playList && this.$refs.playList.refresh() }
  • no-result組件的應用
  1. 布局DOM:
    <div class="no-result-wrapper" v-if="noResult">
         <no-result :title="noResultDesc"></no-result>
    </div>
  2. 顯示條件和顯示提示內容都需要動態綁定計算屬性,判斷currentIndex
    noResult() { if(this.currentIndex === 0) { return !this.favoriteList.length }else{ return !this.playHistory.length } }, noResultDesc() { if(this.currentIndex === 0) { return '暫無收藏歌曲' }else{ return '你還沒有聽過歌曲' } } 
  3. 優化:當列表中無數據,點擊隨機播放全部時,rendom()不執行任何操作
    if(list.length === 0) { return }
二、性能優化
  • 坑:快速的點擊播放暫停歌曲,發現歌曲和歌詞還在播放
  1. 原因:player.vue中watch currentSong會做一些清理操作,並在1s內開啟play()播放;此時如果很快的切換歌曲切換播放狀態,調用ready()和watch playing中的pause()會在1s內執行完;雖然看起來pause執行了,但1s過去之后,又會重新開啟play() 
  2. 解決:在每次setTimeout前清理掉舊的timer,保證只有一個timer;同時修改ready的觸發事件為play,保證ready()和pause()一定發生在play()后
  3. 區別:

    ①事件canplay -- 當瀏覽器可以播放音頻/視頻時

    ②事件play -- 當音頻/視頻已開始或不再暫停時

  4. 注: 這里添加clearTimeout(this.timer)時總報timeout.close is not function,top-tip中使用過清理timer,沒有問題,這里就不知道為什么了,待解決!
  • 坑:快速切換歌曲時,歌詞的播放異常
  1. 原因:異步時機問題 -- setTImeout執行1s的操作中play()是一個同步的動作,而getLyric()是異步的操作;在異步獲得回調時,有可能又切換到了下一首歌,這時之前的歌會在new一次,相當於new了兩次,會有多個歌詞同時存在
  2. 解決:在異步獲得回調后先判斷currentSong.lyric是否改變了,如果改變了不為layric,不執行任何操作
    if(this.currentSong.lyric !== lyric){ return } 
  • 坑:當前歌曲只有一首歌時,切換下一首,不會再觸發ready()了
  1. 原因:next()中當列表長度為1時,會調用loop(),后面的ready標志位會一直為false,redy()也就不會再觸發了
  2. 解決:在next()和prev()中,如果調用了loop()就直接return,不再修改標志位為false
三、項目打包及VConsole的使用

       編譯打包 

npm run build

       VConsole的使用  

  • 安裝
  1. 在頁面引入一個JS文件:下載地址
  2. 使用npm安裝
    npm install vconsole
  • 使用webpack,然后在js代碼中應用VConsole
    import VConsole from 'vconsole/dist/vconsole.min.js' //引入vconsole
    let vConsole = new VConsole() // 初始化
    或者找到這個模塊下面的 dist/vconsole.min.js ,然后復制到自己的項目中
    <head>
        <script src="dist/vconsole.min.js"></script>
    </head>
    <!--建議在 `<head>` 中引入哦~ -->
    <script>
      // 初始化
      var vConsole = new VConsole(); console.log('VConsole is cool'); </script>

注:項目來自慕課網


免責聲明!

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



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