? ?? ?? vue-music? Player ????? ?? ?? ??? ???? ???? ????. ?? ?? ???? ??? ? ????.
? ?? ??? Player ????? ?? ????. ??? ???? ??? ??? ????
?? ????:
1. ? ????? ???? ?? ??? ????. ?? vuex state.js
import {playMode} from 'common/js/config.js'; const state = { singer:{}, playing:false, //是否播放 fullScreen:false, //是否全屏 playList:[], //播放列表 sequenceList:[], // 非順序播放列表 mode:playMode.sequence, // 播放模式(順序0,循環(huán)1,隨機2) currentIndex:-1, //當前播放索引 } export default state --------------------------------------------- // config.js export const playMode = { sequence:0, loop:1, random:2 }
2?? ?? ???? ??? ?????. ???? ???? ??? ? ?? ?? ???? ???? ?? ??? ?????. ?? ?? ???? ??
?? ?? ?? ??? ?? ??? ???? ?????. ????, ?? ??? ??? ???? ?????
<li @click="selectItem(song,index)" v-for="(song,index) in songs" class="item"> ------------------------------ selectItem(item,index){ this.$emit('select',item,index) },
?? ?? ?????? ?? ???? ????.
<song-list :rank="rank" :songs="songs" @select="selectItem"></song-list>
3. ?? ??? ???? ??
import {playMode} from 'common/js/config.js' export const selectPlay = function({commit,state},{list,index}){ commit(types.SET_SEQUENCE_LIST, list) commit(types.SET_PLAYLIST, list) commit(types.SET_CURRENT_INDEX, index) commit(types.SET_FULL_SCREEN, true) commit(types.SET_PLAYING_STATE, true) }
4. mapActions? ???? ?? ?? ?? ??? ??? ?? ?????.
import {mapActions} from 'vuex' methods:{ selectItem(item,index){ this.selectPlay({ list:this.songs, index }) }, ...mapActions([ 'selectPlay' ]) },
5. ?? ?? (?? ?? ??? ?? ??? ????? ??? ???? ? ????)
<p class="player" v-show="playList.length>0"> // 如果有列表數(shù)據(jù)則顯示 <p class="normal-player" v-show="fullScreen"> //如果全屏 <p class="background"> <img :src="currentSong.image" alt="" width="100%" height="100%"> //模糊背景圖 </p> <p class="top"> <p class="back" @click="back"> <i class="icon-back"></i> </p> <h1 class="title" v-html="currentSong.name"></h1> //當前歌曲名稱 <h2 class="subtitle" v-html="currentSong.singer"></h2> //當前歌手名 </p> <p class="middle"> <p class="middle-l"> <p class="cd-wrapper"> <p class="cd" :class="cdCls"> <img :src="currentSong.image" alt="" class="image"> //封面圖 </p> </p> </p> </p> <p class="bottom"> <p class="progress-wrapper"> <span class="time time-l">{{ format(currentTime) }}</span> <p class="progress-bar-wrapper"> <progress-bar :percent="percent" @percentChange="onProgressBarChange"></progress-bar> </p> <span class="time time-r">{{ format(currentSong.duration) }}</span> </p> <p class="operators"> <p class="icon i-left"> <i :class="iconMode" @click="changeMode"></i> </p> <p class="icon i-left" :class="disableCls"> <i @click="prev" class="icon-prev"></i> </p> <p class="icon i-center" :class="disableCls"> <i :class="playIcon" @click="togglePlaying"></i> </p> <p class="icon i-right" :class="disableCls"> <i @click="next" class="icon-next"></i> </p> <p class="icon i-right"> <i class="icon icon-not-favorite"></i> </p> </p> </p> </p> </transition> <transition name="mini"> <p class="mini-player" v-show="!fullScreen" @click="open"> <p class="icon"> <img :src="currentSong.image" alt="" width="40" height="40" :class="cdCls"> </p> <p class="text"> <h2 class="name" v-html="currentSong.name"></h2> <p class="desc" v-html="currentSong.singer"></p> </p> <p class="control"> <i :class="miniIcon" @click.stop="togglePlaying"></i> </p> <p class="control"> <i class="icon-playlist"></i> </p> </p> </transition> <audio :src="currentSong.url" ref="audio" @canplay="ready" @error="error" @timeupdate="updateTime" @ended="end"></audio> </p>
???? ?? ??
import {mapGetters,mapMutations} from 'vuex'; ...mapGetters([ 'fullScreen', 'playList', 'currentSong', 'playing', 'currentIndex', ])
??: vuex?? ??? ???? ?? ????? ?? ?? ??? ?? ????. This.fullScreen = false? ????? ?? ????? ???. ???? ?? ? ????? ??? ?? vuex? mapMutations ??? ???? ????
[types.SET_FULL_SCREEN](state, flag) { state.fullScreen = flag }, import {mapGetters,mapMutations} from 'vuex'; methods:{ ...mapMutations({ setFullScreen:"SET_FULL_SCREEN", }), back(){ this.setFullScreen(false) }, }
? ???? ?? ?? ?? ???
<i :class="playIcon" @click="togglePlaying"></i>
togglePlaying(){ this.setPlayingState(!this.playing); //改變全局變量playing 的屬性 }, // 然后watch 監(jiān)聽playing 操作實際的audio 標簽的播放暫停 watch:{ playing(newPlaying){ let audio = this.$refs.audio; this.$nextTick(() => { newPlaying ? audio.play():audio.pause(); }) } }, // 用計算屬性改變相應的播放暫停圖標 playIcon(){ return this.playing? 'icon-pause':'icon-play' },
? ?????. -?? ? ?? ?? ?? ??? ?????. mapGetters? ???? currentIndex ?(??? 1 ?? ?? 1)? ??? ?????? currentSong? ??? ???? ?? ??? ?????. ?? ?? ?? ???? ?????.
prev(){ if(!this.songReady){ return; } let index = this.currentIndex - 1; if(index === -1){ //判斷播放列表界限重置 index = this.playList.length-1; } this.setCurrentIndex(index); if(!this.playing){ //判斷是否播放改變播放暫停的icon this.togglePlaying(); } this.songReady = false; }, next(){ if(!this.songReady){ return; } let index = this.currentIndex + 1; if(index === this.playList.length){ //判斷播放列表界限重置 index = 0; } this.setCurrentIndex(index); if(!this.playing){ this.togglePlaying(); } this.songReady = false; },
?? ??? ? ??? ?? ??? canpaly ???? ??, ??? ??? ???? error ???? ?? ???? ??? ???? ??? ???? ?? ??? ? ?? ??? ??? ?????.
songReady ???? ?????. ??? ???? ?? ?? ?? ??? ??? ? false? ?? ?????.
data(){ return { songReady:false, } }, ready(){ this.songReady = true; }, error(){ this.songReady = true; },
?? ???
??? ??? ??? ??-?? ?? ?????? ?? ?? timeupdate ???? ?????. ?? ??. ?? ?? ??? ????? ??? ?????. (_pad? ?? ?? ?????.)
? ??? ?? ?? ???? currentSong.duration
<p class="progress-wrapper"> <span class="time time-l">{{ format(currentTime) }}</span> <p class="progress-bar-wrapper"> <progress-bar :percent="percent" @percentChange="onProgressBarChange"></progress-bar> </p> <span class="time time-r">{{ format(currentSong.duration) }}</span> </p> <audio :src="currentSong.url" ref="audio" @canplay="ready" @error="error" @timeupdate="updateTime" @ended="end"></audio>
updateTime(e){ this.currentTime = e.target.currentTime; // 獲取當前播放時間段 }, format(interval){ interval = interval | 0; const minute = interval/60 | 0; const second = this._pad(interval % 60); return `${minute}:${second}`; }, _pad(num,n=2){ let len = num.toString().length; while(len<n){ num = '0' + num; len ++; } return num; },
?? ??? ?? ??? ???, ?? ?? ?? ??? ??, ?? ???? ??? ???? ?? ??. ???? ?? ??? ??? ?? ???? ?????
percent(){ return this.currentTime / this.currentSong.duration // 當前時長除以總時長 },
progress-bar ?? ??
<p class="progress-bar" ref="progressBar" @click="progressClick"> <p class="bar-inner"> <p class="progress" ref="progress"></p> <p class="progress-btn-wrapper" ref="progressBtn" @touchstart.prevent="progressTouchStart" @touchmove.prevent="progressTouchMove" @touchend="progressTouchEnd" > <p class="progress-btn"></p> </p> </p> </p>
const progressBtnWidth = 16 //小球寬度 props:{ percent:{ type:Number, default:0 } }, watch:{ percent(newPercent){ if(newPercent>=0 && !this.touch.initated){ const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth; const offsetWidth = newPercent * barWidth; this.$refs.progress.style.width = `${offsetWidth}px`; this.$refs.progressBtn.style.transform=`translate3d(${offsetWidth}px,0,0)` } } }
Set drag
?? ??? ?? ?? ProgressBtn? touchstart, touchmove, touchend ??? ?? ??? ???? ???? ??? ?????. ?? ?? ????? ???? ???? ???? ??? ?? ??? ??? ????
????? ?? ??? ???? ?? ?? ?? ?? ?? ? ?? ?? ??? ?????. touchstart ??? ????? ?? this.touch.initiated? true? ???? ???? ?????? ?????. ?? ?? ?? e.touches[0].pageX? ???? ?? ?? ??? ???? ?? ?? ?? ?????.
touchmove??? ?? ???? ??? ?????? ????, ??? ???? ?? ?? ??? ??? ??? ? ?? ?????. let deltax = e.touches[0].pageX - this.touch.startX
? ??? ???? ?? ??? ??? ??? ?? ??? ? ????. ?? ??? ?? ??? ???? ??? ??? ? ????
??? ???? ??? ????? this._offset(offsetWidth) ???? ?????.
??? ??? ????? ???? ??? ????? this.touch.initiated? false? ?????. ???? ???? ?? ??? ?????. ???? currentTime ?? ??? ??? ?????. ????? pencent
??? ???? ?? ???? ????, this._offset(e.offsetX)? ????, ???
created(){ this.touch = {}; }, methods:{ progressTouchStart(e){ this.touch.initiated = true; this.touch.startX = e.touches[0].pageX; this.touch.left = this.$refs.progress.clientWidth; }, progressTouchMove(e){ if(!this.touch.initiated){ return; } let deltaX = e.touches[0].pageX - this.touch.startX; let offsetWidth = Math.min(this.$refs.progressBar.clientWidth - progressBtnWidth,Math.max(0,this.touch.left + deltaX)); this._offset(offsetWidth); }, progressTouchEnd(e){ this.touch.initiated = false; this._triggerPercent(); }, progressClick(e){ const rect = this.$refs.progressBar.getBoundingClientRect(); const offsetWidth = e.pageX - rect.left; this._offset(offsetWidth); // this._offset(e.offsetX); this._triggerPercent(); }, _offset(offsetWidth){ this.$refs.progress.style.width = `${offsetWidth}px`; this.$refs.progressBtn.style[transform] = `translate3d(${offsetWidth}px,0,0)`; }, _triggerPercent(){ const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth; const percent = this.$refs.progress.clientWidth / barWidth; this.$emit("percentChange",percent) } },
? ?????. ? ?? "Vue.js ????? ?? ?? ??" ????"? ???? ???, ??? ??? ?? ? ????.
vue.js ?? ??? ?? ????? ??? ??? vue.js ?? ?? ?? ????? ???? ?????.
? ?? Vue ?? ????? ??? ?? ?? "Vue Practical Tutorial"? ?????.
? ??? ?? ???? ?? ??? ?????. ??? ??? ?? ????.
?? ??:
vue.js? mint-ui? ??? ??? ???? ??
?? ??? ???? ????? ?? ??? ????? Jstree?? ???? ??
? ??? vue-music?? Player ?? ??? ???? ??? ?? ??? ?? ?????. ??? ??? PHP ??? ????? ?? ?? ??? ?????!

? AI ??

Undress AI Tool
??? ???? ??

Undresser.AI Undress
???? ?? ??? ??? ?? AI ?? ?

AI Clothes Remover
???? ?? ???? ??? AI ?????.

Clothoff.io
AI ? ???

Video Face Swap
??? ??? AI ?? ?? ??? ???? ?? ???? ??? ?? ????!

?? ??

??? ??

???++7.3.1
???? ?? ?? ?? ???

SublimeText3 ??? ??
??? ??, ???? ?? ????.

???? 13.0.1 ???
??? PHP ?? ?? ??

???? CS6
??? ? ?? ??

SublimeText3 Mac ??
? ??? ?? ?? ?????(SublimeText3)

??? Python ? ?? ????? ????? ?? ??? ?????. 1. Django ?? Flask? ?? ??? ??? ??? ??????. 2. ??????? ???? sqlalchemy? ?? ORM? ??????. 3. ??? ??? ???? Vue ?? React? ??????. 4. ???? ???? Pytest ?? UnitTest? ??????. 5. ?? ????? ???? Docker ? Heroku ?? AWS? ?? ???? ??????. ??? ??? ?? ???? ???? ? ?? ????? ?? ? ? ????.

??? ?? ??? ???? ??? URL? ?? ??? ???? ????. Vuerouter ? Reactrouter? URL ??? ?? ?? ?? ??????? ?? ???? ??? ??? ?????. ?? ???? ??? ?????. 1. ?? ???, ?? ?? ??? ?? ?? ?? ??? ?????. 2. ?? ???, URL ?? ??? ?? ?? ?? ?? ??; 3. Route Guard, ?? ?? ??? ?? ??? ?? ?? ??.

??? transforminvue3aimedtosimplify handlingreactivedatabyautomicallytrackingandmaningreactivity withoutequiringmanualref () ?? valueusage.itsivingtoreduceboilerplateandimprovecodeReadabilitabledevariableletandsconstasmonclicallicallicallicallicallicallicallicallicallicallicallicalliceLerplateNclateMconsconclicallicallicallicallicallicallicallicallicalliceLerplateN

vue.js? ?? ?? ???? React ?? ?? ??? ??? ????. 1) vue.js? ??? ??? ?? API? ???? ?? React? JSX ? ?? ?? ??? ?????. 2) vue.js? ?? ? ???? ???? React? ??? ???? ?? DOM? ?????. 3) vue.js? ?? ???? ??? ???? ?? React? ? ?? ??? ??? ?????.

??? ? ??? invueAppsareprimally handledusingthevuei18nplugin.1.installvue-i18nvianpmoryarn.2.createlocalejsonfiles (? : en.json, es.json) fortranslationMessages.3

vue.js? ?? ????? ?? ? ? ?? .defineProperty? ?? ??? ?? ?? ?? ?????? ?????? ????. ???? ??? ????. 1. VUE.SET ???? ???? ?? ???? ?????. 2. ?? ??? ? ??????. 3. VUE? ? ?? ? ???? ??? ???? ??? ??????.

?? : keyAttributeWithv-forInvueisSenderferperferformanCanceAndCorrectBehavior.first, ithelpsVuetrackeachelementementEficiledullyBirtlyBirtlyDiffingAlgorithMtoIndifyandUpdateOnlyWhat'Snecessary.second, itpreservescomponents, ensuri

VUE? ?? ?? ? ??? ?? ??? ??? ????? ?? : 1. V-Once ???? ???? ?? ???? ???? ???? ????? ????. 2. ?? ???? ???? Vue-Virtual-Scroller ????? ??? ?? ??? ??? ?? ? ??????. 3. ?? ???? ??? ?? Keep-Alive ?? V-Once? ?? ?? ?? ??; 4. ?? ? ?? ? ???? ???? ?? ? ??? ????? ? ??? ??? ????. 5. V-FOR?? ?? ? ??, ???? ??? ??? ??? ?? ?? ??? ???? ?? ??? ?? ? ?? ??? ?????. ??? ??? ?? ???? ????? ???? ? ????.
