vue09----vuex輔助函數、Detail.vue跳轉Player.vue、封裝mutations中的函數名、utils工具的使用、&符號、audio標簽的timeupdate事件和ended事件、點擊play按鈕實現播放和暫停,同時img對應旋轉或暫停旋轉、上一曲(prev)和下一曲(next)、props傳值以對象形式對象接收、watch監聽控制進度條的寬度、點擊滾動條控制播放時間


### 樣式作用域

    scoped

 

### vuex的輔助函數(Player.vue)

    mapState:將state值直接映射到計算屬性
 
        原來拿到state中的songList:
            computed: {
                songList(){
                    return this.$store.state.songList;
                }
            }
        通過mapState拿到state中的songList:
            computed: {
                ...mapState(["songList"])
            }
 
    步驟:
        ①引入
            import {mapState,mapMutations,mapActions,mapGetters} from "vuex";
        ②computed中使用...mapState()拿到store中state中的屬性,使用...mapGetters拿到store中getters中的方法
            computed: {
                // songList(){
                //     return this.$store.state.songList.length;
                // }
                ...mapState(["songList","fullScreen","currentIndex"]),
                // currentSong(){
                //     return this.$store.getters.currentSong
                // }
                ...mapGetters(["currentSong"])
            }

 

### 點擊Detail.vue列表歌曲,跳轉至Player.vue

    ①在store.js中,聲明歌單列表和當前播放歌曲的下標
        const store=new Vuex.Store({
            state:{
                playing:false,
                fullScreen:false,
                songList:[],     // 歌單列表
                currentIndex:-1,     // 當前正在播放的歌曲
            },
            mutations:{
                setSongList(state,list){
                    state.songList=list;
                },
                setCurrentIndex(state,index){
                    state.currentIndex=index;
                }
            },
            getters:{
                currentSong(state){
                    // 根據下標獲取當前播放歌曲的信息
                    return state.songList[state.currentIndex];
                }
            }
        })
    ②Detail.vue中通過goPlayer()方法中的commit()觸發mutations中的方法,將當前歌手的歌單列表和當前下標分別傳過去
        goPlayer(index){
            this.$store.commit("setSongList",this.list);
            this.$store.commit("setCurrentIndex",index);
        }
    ③Player.vue中,可以通過getters拿到
        {{this.$store.getters.currentSong}}

 

        這個取值的方法太繁瑣了,可以通過輔助函數mapGetters拿到:
            computed: {
                ...mapGetters(["currentSong"])
            }
        然后就{{currentSong}}就可以了

 

    最好是通過actions來觸發,稍作修改:
        store.js中:
            actions:{
                addSongList({commit},{index,list}){
                    commit("setSongList",list);
                    commit("setCurrentIndex",index);
                }
            },
        Detail.vue中:
            goPlayer(index){
                // this.$store.commit("setSongList",this.list);
                // this.$store.commit("setCurrentIndex",index);
                this.$store.dispatch("addSongList",{list:this.list,index:index});
            }
        注意:actions的用途就是處理異步和做多個commit的封裝。

 

### 利用const將mutations中函數的名字做封裝,避免命名重復(store.js)

    ①store文件夾下新建mutations-type.js文件:
        const SET_SONG_LIST="SET_SONG_LIST";
        const SET_CURRENT_INDEX="SET_CURRENT_INDEX";
 
        export default{
            SET_SONG_LIST,
            SET_CURRENT_INDEX
        }
    ②store.js中用常量名替代原來的函數名:
        引入:
        import type from "./mutations-type.js"
        mutations和actions中:
            mutations:{
                [type.SET_SONG_LIST](state,list){
                    state.songList=list;
                },
                [type.SET_CURRENT_INDEX](state,index){
                    state.currentIndex=index;
                }
            },
            actions:{
                addSongList({commit},{index,list}){
                    commit(type.SET_SONG_LIST,list);
                    commit(type.SET_CURRENT_INDEX,index);
                }
            },

 

### utils工具的使用(Player.vue)

    ①在src下新建utils/formatUrl.js:
        // 專輯
        export const albumUrl=(albumMid)=>{
            return `https://y.gtimg.cn/music/photo_new/T002R300x300M000${albumMid}.jpg?max_age=2592000`;
        }
        // 歌曲
        export const songUrl=(songMid)=>{
            return `http://aqqmusic.tc.qq.com/amobile.music.tc.qq.com/C400${songMid}.m4a?guid=4887996690&vkey=16121C6B6E73C564FA01F98651C808B32B6D8788E8C7A1FCCFD030B194EC90658BB78D0A988B6DBC9F0C6E1535FD194E2C459CE01510E438&uin=0&fromtag=38`;
        }
    ②引入:(Player.vue)
        import * as urlObj from "utils/formatUrl.js";
        或
        import {albumUrl,songUrl} from "utils/formatUrl.js";
    注意:
        1、export default{} 只能拋出一個對象,如果要拋出多個用 export const ...
        2、引入的時候加上 * as,或者通過解構:import {albumUrl,songUrl} from "utils/formatUrl.js";

 

### &符號的意思(Player.vue)

    img{
        .w(300);
        .h(300);
        border-radius: 50%;
        border: 10px solid hsla(0,0%,100%,.1);
        box-sizing: border-box;
        &.play{
            animation: rotate 20s linear infinite;
        }
        &.paused{
            animation-play-state: paused;
        }
    }
    加&表示play、paused和img是同級的,不加&表示play、paused是img的子級。

 

### audio標簽的timeupdate事件:當前播放時間(Player.vue)

    audio綁定timeupdate事件,可以通過e.target.currentTime拿到當前播放時間
    ①定義timeupdate事件
    <audio controls @timeupdate="timeUpdate"></audio>
    ②將當前時間賦給current當前時間
        timeUpdate(e){
            console.log("時間變化",e.target.currentTime)
            this.current=e.target.currentTime;
        }

 

### 點擊play按鈕,實現播放和暫停,播放時img旋轉,暫停時img暫停旋轉(Player.vue)

    ①給img標簽綁定類名playClass
        <img :class="playClass" v-if="currentSong" :src="albumUrl">
    ②按鈕添加點擊事件play
        <div class="control">
            <button @click="play">play</button>
        </div>
    ③data中聲明playing為false
        data() {
            return {
                playing:false
            }
        }
    ④設置play和paused類名的樣式
        img{
            .w(300);
            .h(300);
            border-radius: 50%;
            border: 10px solid hsla(0,0%,100%,.1);
            box-sizing: border-box;
            &.play{
                animation: rotate 20s linear infinite;
            }
            &.paused{
                animation-play-state: paused;
            }
        }
    ⑤computed中將playing的值賦給playClass類
        playClass(){
            return this.playing?"play":"play paused";
        }
        接下來控制playing的布爾值就可以控制img的旋轉
    ⑥play()方法中判斷是否處於暫停中,如果是點擊播放,否則點擊暫停,同時設置playing值
        play(){
            let audio=this.$refs.audio;
            if(audio.paused){
                audio.play();
                this.playing=true;
            }else{
                audio.pause();
                this.playing=false;
            }
            console.log(audio.__proto__)
        }
    注意:
        1、添加類名的時候不可以寫 return this.playing?"play":"paused"; 這樣會造成暫停過后,img重新開始旋轉。
        2、打印audio標簽的__proto__對象,可以獲取audio的一系列屬性和方法。

 

### 上一曲(prev)和下一曲(next)(Player.vue)

    ①添加prev和next按鈕:
        <div class="control">
            <button @click="prev">prev</button>
            <button @click="play">play</button>
            <button @click="next">next</button>
        </div>
    ②通過commit()觸發mutations中的SET_CURRENT_INDEX方法:
        next(){
            let index=this.currentIndex+1;
            this.$store.commit("SET_CURRENT_INDEX",index);
        },
        prev(){
            let index=this.currentIndex-1;
            this.$store.commit("SET_CURRENT_INDEX",index);
        }
    ③邊界判斷,當SET_CURRENT_INDEX方法中判斷當index大於列表最后一項時,讓index為0;當index小於列表第一項時,讓index為列表最后一項。這就是循環播放:
        [type.SET_CURRENT_INDEX](state,index){
            if(index>state.songList.length-1){
                index=0;
            }else if(index<0){
                index=state.songList.length-1;
            }
            state.currentIndex=index;
        },

 

### audio標簽的ended事件:播放完成觸發(Player.vue)

    ①
    <audio controls @ended="ended"></audio>
    ②
    ended(){
          console.log("播放完成")
    }

 

### props傳值(Player.vue、P-scrollBar.vue)

    props用於父傳子傳值。
 
    傳遞:當子組件在父組件中當做標簽傳值使用的時候,給當前子組件綁定一個自定義屬性,值為需要傳遞的數據。
        <one :val="msg"></one>
 
    接收:在子組件內部通過props屬性來進行接收。props接收的方式有數組和對象兩種:    
        數組接收:
          props:["msg"]
        對象接收:
          props:{
                    msg:{
                        type:Number,
                        default:0,
                        required:true
                    }
                }
            type:限制外部數據的類型
            default:默認值,當父組件沒有給子組件傳值時用默認值
            required:布爾值,當前屬性是不是必傳的值,如果值為true,不傳msg屬性時會報錯
 
    傳遞:(Player.vue)
        <PScrollBar :current="current" :duration="duration"></PScrollBar>
    接收:(P-scrollBar.vue)
        props:{
            "current":{type:Number,default:0},
            "duration":{type:Number,default:0},
        }

 

### watch監聽控制進度條的寬度(P-scrollBar.vue)

    watch: {
        current(newValue){
            let percentage=(newValue/this.duration)*100;
            this.$refs.container.style.width=`${percentage}%`;
        }
    }
    注意:watch中的方法是data中的屬性,watch依賴於data,當data中的屬性發生改變的時候,觸發watch中函數執行。current()是data中的屬性,這里它是由props傳遞過來的,當current()執行時,進度條寬度被不斷地重新定義。

 

### 點擊滾動條控制播放時間(P-scrollBar.vue)

    ①給wrapper盒子綁定點擊事件clickDarg
        <div class="wrapper" @click="clickDarg" ref="wrapper">
            <div class="container" ref="container">
 
            </div>
        </div>
    ②將比例賦給container盒子,並將這個百分比傳給父組件Player.vue
        clickDarg(e){
            let percentage=(e.offsetX/this.$refs.wrapper.clientWidth)*100;
            this.$refs.container.style.width=`${percentage}%`;
            // 派發jump事件給Player.vue
            this.$emit("jump",percentage);
        }
    ③給PScrollBar組件綁定jump事件
        <PScrollBar :current="current" :duration="duration" @jump="jump"></PScrollBar>
    ④audio的currentTime屬性可讀也可寫
        jump(percentage){
            this.$refs.audio.currentTime=this.duration*percentage/100;
        }

 


免責聲明!

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



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