炎炎夏日,劇烈的高溫也抵擋不住對學習的堅持。對於學習,不少時候都會有鬆懈和逃避的心理,但看到身邊近乎瘋狂的考研黨們,我仍是選擇了堅持。距離上次發文章已經有一個月之久了,期間學習了不少知識,越學習愈加以爲本身的路還有很長,但既然選擇了遠方,便只顧風雨兼程了。css
mpvue 是一個使用 Vue.js 開發小程序的前端框架。框架基於 Vue.js 核心,mpvue 修改了 Vue.js 的 runtime 和 compiler 實現,使其能夠運行在小程序環境中,從而爲小程序開發引入了整套 Vue.js 開發體驗。前端
關於模擬數據這裏提一個網易雲音樂api,真的很強但因爲小程序不支持本地域名的request請求,須要部署到服務器上變爲小程序合法域名,因爲精力有限這裏只是截取了部分數據進行模擬。有興趣的小夥伴能夠本身玩玩啊。vue
寫這個項目的時候,碰到了不少問題,BUG更是很多,在mpvue與原生小程序中瘋狂糾結,因爲時間精力有限,目前只完成了三個頁面,重點把核心播放功能完成了大半。因爲網上關於mpvue的資源不多,遇到問題都是在瘋狂百度,嘗試等等方法也算是解決了部分。這裏分享我遇到的一些困難,但願能幫助到有須要的人。git
npm install flyio
es6
import Vue from 'vue'
var Fly = require('flyio/dist/npm/wx.js') //wx.js爲flyio的微信小程序入口文件
var fly = new Fly();
fly.interceptors.request.use((config,promise)=>{
config.headers["X-Tag"]="flyio"; //給全部請求添加自定義header
return config;
})
//配置請求基地址
fly.config.baseURL="https://www.easy-mock.com/mock/5b372361808a747e8d04a1e3/"
Vue.prototype.$http=fly //將fly掛載在vue上供全局使用
export default fly
複製代碼
npm install vuex
this.$store.state.xxx
,this.$store.dispatch
等來訪問或操縱數據倉庫中的數據new Vue({
el: '#app',
store,
router,
template: '<App/>',
components: { App }
})
複製代碼
注意了,在mpvue + vuex項目中,很遺憾不能經過上面那種方式來將store對象實例注入到每一個子組件中(至少我嘗試N種配置不行),也就是說,在子組件中不能使用this.$store.xxx
,從而致使輔助函數不能正確使用。這個時候咱們就須要換個思路去實現,要在每一個子組件中可以訪問this.$store
才行。既然咱們須要在子組件中用this.$store
訪問store實例,那咱們直接在vue的原型上添加$store屬性指向store對象不就行啦,因而解決方案以下:github
Vue.prototype.$store = store
web
src下新建一個store文件夾,目錄結構以下vuex
action.js //提交mutation以達到委婉地修改state狀態,可異步操做
getters.js //獲取store內的狀態
index.js //引入vuex,設置state狀態數據,引入getter、mutation和action
mutation-type.js //將方法與方法名分開便於查看
mutations.js //更改store中狀態用的函數的存儲之地
state.js //存放state
複製代碼
這裏展現下index.js內容vue-cli
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import state from './state'
import mutations from './mutations'
Vue.use(Vuex)
export default new Vuex.Store({
actions,
getters,
state,
mutations
})
複製代碼
methods: {
...mapMutations({ //es6 展開運算符
saveDetailState: 'SAVE_DETAIL_STATE',
saveMidimg2: 'SAVE_MIDIMG2',
saveMidimg3: 'SAVE_MIDIMG3'
}),
fly
.get('music#!method=get')
.then(res => {
this.menu = res.data.data.menu;
this.midimg = res.data.data.midimg;
this.saveMidimg2(res.data.data.midimg2); //子組件標題數據
this.saveDetailState(res.data.data.footimg);//推薦歌單信息
this.saveMidimg3(res.data.data.midimg3);//
this.footimg2 = res.data.data.footimg2;
this.footimg3 = res.data.data.footimg3;
})
複製代碼
因爲本人開發項目使用的css預編譯器stylus 他會自動補全前綴,而小程序又並不支持-moz- -webkit-等前綴那怎麼辦呢? 解決方案以下:npm
<style lang="stylus">
...
</style>
<style> //不在stylus編譯下
@keyframes rotate {
0%{
transform: rotate(0);}
100% {
transform: rotate(360deg);
}
}
</style>
複製代碼
mounted(){
wx.showLoading({
title: '加載中'
})
this.midshow = true
let options = this.$root.$mp.query;
const songid = options.songid;
const id = options.id;
if(this.audioCtx != null) { //第一次不用銷燬
if(this.song.id != songid){
this.audioCtx.destroy()} //銷燬實例
}
if(this.song.id != songid || this.song.id == '') //同一首歌不用新建
{ this.audioCtx = wx.createInnerAudioContext() //新建實例
}
if(options.name == 'undefined' && this.song.id != songid){ // 同一首歌不用從新更新數據
this.getSong(songid,id) //獲取當前音樂信息
const afterlyric = this.normalizeLyric(this.song.lyric)
this.currentLyric = new Lyric(afterlyric)
...
複製代碼
this.audioCtx.src = this.song.mp3url //設置src
this.allmiao = this.audioCtx.duration //讀取歌曲總時長
const a = setInterval(()=>{
this.allmiao = this.audioCtx.duration
},50)
if(this.allmiao){
clearInterval('a')
}
複製代碼
copmputed: {
width () {
return 'width:'+(this.nowmiao/this.allmiao)*550+'rpx' //盒子寬度總爲550rpx
},
midwidth () {
return 'transform:translate3d('+(this.nowmiao/this.allmiao)*529+'rpx,0px,0px);'
}}
複製代碼
clClick (e) { //點擊進度條事件
const rect = wx.getSystemInfoSync().windowWidth //屏幕總寬
this.offsetWidth = e.pageX - (rect-275)/2 //點擊進度條上距離左側寬度
this.nowmiao = this.allmiao*(this.offsetWidth/275) //根據比例計算點擊位置對應的播放時間
const miao = Math.floor(this.nowmiao)
this.audioCtx.seek(miao) // 跳轉播放
},
// 滑動進度條 分爲start、move、end事件 這個你們應該不陌生,思路都是根據距離計算比例 跳轉時間點播放
clstart (e) {
this.touch.initiated = true
const rect = wx.getSystemInfoSync().windowWidth
this.touch.setWidth = (rect-275)/2
this.touch.startX = e.touches[0].pageX
this.touch.time = this.nowmiao
},
clmove (e) { //這裏要注意進度條臨界點 滑動距離超出的問題
if(!this.touch.initiated) return;
const movex = e.touches[0].pageX - this.touch.startX
if(e.touches[0].pageX>=(this.touch.setWidth+275)) {this.nowmiao =this.allmiao }
else if(e.touches[0].pageX<=this.touch.setWidth) {this.nowmiao = 0;}
else {this.nowmiao = this.touch.time+this.allmiao*movex/275}
},
clend (e) {
this.touch.initiated = false
const miao = Math.floor(this.nowmiao)
this.audioCtx.seek(miao)
},
複製代碼
<scroll-view class="lyric-wrapper" :scroll-into-view="'line'+toLineNum" scroll-y scroll-with-animation>
<view v-if="currentLyric">
<view :id="'line'+i" class="text" :class="[currentLineNum == i ? 'current': '' ]" v-for="(item,i) of currentLyric.lines" :key="i">
{{item.txt}}
</view>
</view>
<view v-if="!currentLyric">
<view class="text current">暫無歌詞</view>
</view>
</scroll-view>
複製代碼
將歌詞進行處理後v-for輸出 經過id、class分別進行滾屏與當前播放歌詞行的高亮
normalizeLyric: function (lyric) {//將歌詞數據進行拆分
return lyric.replace(/:/g, ':').replace(/ /g, '\n').replace(/./g, '.').replace(/ /g, ' ').replace(/-/g, '-').replace(/(/g, '(').replace(/)/g, ')')
},
const afterlyric = this.normalizeLyric(this.song.lyric)
this.currentLyric = new Lyric(afterlyric) //建立Lyric實例
this.audioCtx.onTimeUpdate(()=>{ //音頻播放進度更新事件
this.nowmiao = this.audioCtx.currentTime //當前播放時間
if (this.currentLyric) {
this.handleLyric(this.nowmiao * 1000) //歌詞行處理函數
}
})
handleLyric (currentTime) { //控制歌詞滾屏 隨播放進度不斷觸發
let lines = [{time: 0, txt: ''}], lyric = this.currentLyric, lineNum
lines = lines.concat(lyric.lines) //進行歌詞對應時間、內容
//判斷當前播放時間位置 進行歌詞行的調整 使其當前歌詞部分處於中間,若開頭則從頭部往下,尾部反之
for (let i = 0; i < lines.length; i++) {
if (i < lines.length - 1) {
let time1 = lines[i].time, time2 = lines[i + 1].time
if (currentTime > time1 && currentTime < time2) {
lineNum = i - 1
break;
}
} else {
lineNum = lines.length - 2
}
}
this.currentLineNum = lineNum,
this.currentText = lines[lineNum + 1] && lines[lineNum + 1].txt
let toLineNum = lineNum - 5
if (lineNum > 5 && toLineNum != this.toLineNum) {
this.toLineNum = toLineNum
}
},
複製代碼
在項目中有不少部分是很是類似的,將這部分進行組件封裝經過v-if、class、style等進行添加修改組件部分,組件封裝要易於維護,高性能,低耦合。這裏展現下首頁中部組件
<scroll-view scroll-y="true" enable-back-to-top="true" class="mid-top">
<swiper-t :menu="menu"></swiper-t>
<mid-t :midimg="midimg"></mid-t>
<foot-t :footimg="footimg" :footname="footname1"></foot-t>
<foot-t :footimg="footimg2" :footname="footname2"></foot-t>
<foot-t :footimg="footimg3" :footname="footname3"></foot-t>
</scroll-view>
複製代碼
雖然只是寫了三個頁面,但也確實讓我體會到了mpvue框架好用的地方,對於那些不太熟悉小程序對vue比較熟悉的人mpvue是一個好用的框架了,但還有不少地方須要完善。文章寫到這裏其實還有東西可寫,好比切歌 播放模式等等,這裏就不一一闡述了。寫文章,志在分享,志在認識更多志同道合的盆友,也算是本身的一個總結梳理吧。這裏附上個人項目地址,有興趣的朋友能夠看看玩玩,幫忙點個star~做爲一個即將出去闖蕩的大三學生,時間是真的很寶貴,對待學習也不敢懈怠,若是你有什麼好的建議或者問題歡迎加我qq:1404827307,寫文章不易,且贊且珍惜。前端路漫漫,穩步向前行!