vue專案---仿寫音樂app----遇到的問題及解決總結
0.https://y.qq.com/m/index.html 1. 基於router-link的導航跳轉 : html: <router-link tag="div" :to="item.path" class="tab-item tCenter" v-for="(item,index) in tabLists" exact ><span class="tab-link">{{item.title}}</span></router-link> css: .tab-link padding-bottom:5px &.router-link-active .tab-link color:#ffcd32 border-bottom:2px solid #ffcd32 js: tabLists:[{"path":"/","title":"推薦"},{"path":"/singer","title":"歌手"},{"path":"/rank","title":"排行"},{"path":"/search","title":"搜尋"}], index.js: { path: '/', component: Home, children:[{ path: '/', component: Recommend, }, { path: '/singer', component: Singer, },{ path: '/rank', component: Rank, },{ path: '/search', component: Search, }] } 注意:以上程式碼中 exact關鍵字 能幫助只允許一個router-link被啟用,&.router-link-active定義了標籤被啟用的樣式。 2. 在vue中引用模組函式,
3. jsonp是可以實現跨越請求獲取資料的,不是通過ajax,是通過新建一個標籤,其src指向從而實現跨越請求。 //引入jsonp import originJsonp from "jsonp" //封裝一個名叫jsonp的函式,url表示純地址,data表示地址後面的引數,option為第三方外掛jsonp的引數,返回一個promise,在這個promise中呼叫原始的第三方外掛jsonp //根據執行的結果的是否儲存執行promise export default function jsonp (url,data,option){ url+=(url.indexOf("?")<0?"?":"&")+param(data); //拼接url,如有原引數url有?號表示已經存在至少一個引數了,直接在後面拼接&,然後拼接param(data),如果沒有?則先拼接?在拼接param(data) //最後拼接的樣式如:https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg?g_tk=5381&uin=0&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=h5&needNewCode=1&_=1533171846949 return new Promise((resolve,reject)=>{ originJsonp(url,option,(err,data)={ //呼叫第三方外掛jsonp if(!err){ resolve(data) }else{ reject(err) } }) }) } //定義一個param函式,將引數data拼接在一起 data 格式{uname:"Ace",upwd:"123456"} function param(data){ let url=""; for(var k in data){ let val=data[k] !== undefined ? data[k]:""; url+=`&${k}=${encodeURLCompoent(val)}` ; //ncodeURLCompoent是url地址的格式轉換,讓瀏覽器能識別 } //拼接結果的url = &uname=Ace&upwd=123456 return url? url.substring(1):""; //如果url存在就去掉第一個&返回uname=Ace&upwd=123456,否則返回“” }
4. 封裝一個介面函式,呼叫該函式,直接向介面發生jsonp獲取介面的資料 import jsonp from "../common/js/jsonp.js" //引用jsonp獲取recommend推薦相關的資料 import {commonParams,options} from "./config.js" //獲取通用引數 //https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg介面需要配置如下引數 //g_tk: 5381 //uin: 0 //qq號,沒登入預設為0 //format: json //inCharset: utf-8 //outCharset: utf-8 //notice: 0 //platform: h5 //平臺來源h5 //needNewCode: 1 //_: 1533171846949 export function getRecommend(){ const url="https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg"; const data=Object.assign({},commonParams,{ //Object.assign()是es6的新語法,表示將多個物件合併成一個物件 platform: 'h5', needNewCode:1, uin: 0 }) return jsonp(url,data,options) } //在適當的時候呼叫介面函式getRecommend getRecommend().then((res)=>{ if(res.code===ERR_OK){ console.log(res) } }) 5. 新思路,將通用的對dom操作的封裝成一個通用的js檔案如dom.js,如給標籤新增刪除class樣式,可以封裝成dom函式。可重複使用
6. 新思路:建立一個滑動載入better-scroll的元件,在任何時候,需要頁面滑動的時候,包裹該元件即可 <div class="bscroll" ref='wrap'> <slot></slot> //這裡是需要包裹的頁面滑動的內容 </div> import BScroll from "better-scroll" export default{ props:{ data:{ type:Array, default:null }, isClick:{ type:Boolean, default:true }, probeType:{ //該屬性時當 probeType 為 1 的時候,會非實時(螢幕滑動超過一定時間後)派發scroll 事件;當 probeType 為 2 的時候,會在螢幕滑動的過程中實時的派發 scroll 事件 type:Number, //當 probeType 為 3 的時候,不僅在螢幕滑動的過程中,而且在 momentum 滾動動畫執行過程中實時派發 scroll 事件。如果沒有設定該值,其預設值為 0,即不派發 scroll 事件 default:1 }, listenScroll:{ //是否監聽滾動事件的滾動位置,預設情況是不監聽 type:Boolean, default:false } }, mounted(){ this.$nextTick(()=>{ this._initScroll(); }) }, methods:{ _initScroll(){ if(!this.$refs.wrap){return} //即初始化時剛開始傳遞過來的引數可能是undefined this.scroll=new BScroll(this.$refs.wrap,{ click:this.isClick, probeType:this.probeType }) if(this.listenScroll){ //如果呼叫該better-scroll元件傳入的引數要求監聽滾動距離,即this.listenScroll=true,就給better-scroll滾動時通過自定義事件傳遞滾動位置資料 var me=this; this.scroll.on("scroll",(pos)=>{ me.$emit("scroll",pos) }) } }, enable(){ //同步better-scroll的enable方法 this.scroll && this.scroll.enable() }, disable(){ //同步better-scroll的disable方法 this.scroll && this.scroll.disable() }, refresh(){ //同步better-scroll的refresh方法,重新計算滾動高度 this.scroll && this.scroll.refresh() }, scrollTo(){ //同步better-scroll的scrollTo方法,滾動到頁面指定位置高度,因為需要帶有引數,所有用apply()呼叫原來函式 的可傳入引數 this.scroll && this.scroll.scrollTo.apply(this.scroll,arguments) }, scrollToElement(){ //同步better-scroll的scrollToElement方法,滾動到頁面指定位置元素標籤處,因為需要帶有引數,所有用apply()呼叫原來函式 的可傳入引數 this.scroll && this.scroll.scrollToElement.apply(this.scroll,arguments) } }, watch:{ data(){ //傳入的資料發生改變,重新計算滾動高度 this.$nextTick(()=>{ this.refresh(); }) } } } // 引用better-scroll頁面元件 import ReBscroll from "../base/bscroll.vue" <div class="abs recommend"> //注意recommend必須有相對/覺得定位、recommend-scroll繼承父元素的高寬,或者recommend-scroll必須相對絕對定位,且寬高 <re-bscroll class="recommend-scroll"> <div > <!--1.輪播圖--> <re-swiper :imgLists="imgLists" ></re-swiper> <!--2.熱門歌曲列表--> <recommend-list :lists="lists"></recommend-list> </div> </re-bscroll> </div> .recommend width: 100% top: 88px bottom: 0 overflow:hidden .recommend-scroll height: 100% scrollEle(a){ this.$refs.listView.scrollToElement(this.$refs.listGroup[a],0); //接受子元素傳遞過來的字母下標索引,並滾動到該位置 }
7. <img @load="imgLoad"/> //表示圖片的onload載入完成之後執行的函式,如用於,在使用了better-scroll外掛計算滾動高度時,需要在圖片載入完成撐起圖片高度之後,在重新計算滾動高度 即this.refresh(); 如在imgLoad方法中 if(!this.checkload){this.refresh();this.checkload=true } ,表示第一張圖片載入完成之前this.checkload不存在,帶圖片載入完成之後 就執行一次計算滾動頁面高度,然後定義this.checkload=true,之後圖片在載入完成時,應該已經撐起滾動頁面高度,且this.checkload已經存在,避免了很多圖片,每張圖片載入一次 就要重複計算頁面高度的繁瑣執行。 8. vue-lazyload:圖片懶載入的第三外掛,即 頁面滾動到底部時才執行載入更多的圖片,避免的一次性載入太多圖片。 npm install vue-lazyload --save 在main.js中 import VueLazyLoad from "vue-lazyload" Vue.use(VueLazyLoad,{ loading:require("./common/image/default.png"); //載入中暫時存放的圖片,相對main.js的替代圖片的位置 }) 使用: <img v-lazy="url"/> //將src/:src被v-lazy代替即可,也可用於背景圖,詳情見官網 9. swiper無法實現loop:true可能選原因是遠端獲取圖片,遠端的圖片動態不定時改變。
10. 根據物件的key值排序Object.keys(map).sort((a,b)=>{ })
11. vue支援@touchstart事件:<div class="abf tCenter singer-abc" @touchstart="touchWhich"/>
12. 解決[Intervention] Unable to preventDefault inside passive event listener due to target being treated as報錯: 兩個方案: 12.1、註冊處理函式時,用如下方式,明確宣告為不是被動的 window.addEventListener('touchmove', func, { passive: false }) 12.2、應用 CSS 屬性 touch-action: none; 這樣任何觸控事件都不會產生預設行為,但是 touch 事件照樣觸發。 touch-action 還有很多選項, 13. 配置跳轉子路由: 子路由並非真正的頁面,只是覆蓋在父路由上的一層蒙層,所有層級z-index要高 children:[{ path: ':id', component: SingerDetail, }] this.$router.push({ path:`/singer/${a.id}` })