今天,我們來實現播放器首頁的 排行榜頁面 的開發,也就是 src\components\Rank.vue ,效果截圖:

主要分析要點:
1、Vuex模塊化
2、CSS屏幕自適應——@media screen
3、overflow CSS處理文本溢出
4、absolute 絕對定位
頁面的圖片、排行榜名稱、歌曲等信息,來自QQ音樂的數據接口,我們用 vue-resource 插件的 Vue.http.jsonp() 獲取接口數據,這個頁面的難點是CSS布局,主要用到 display:flex 彈性布局,中間還有不少細節,我們一起來分析。
首先,獲取數據,用到的是Vuex,與其在每個需要獲取接口數據的組件里調用接口,還不如將它們統一管理起來,寫成一個公共的函數,通過 Vuex 的 Actions 的 this.$store.dispatch(' ') 獲取即可。
我們來看下具體實現,首先在 src\config 下,新建 api.js ,用於 export 接口地址、參數等信息,方便下一步直接 import 調用,代碼如下:
export default { rank_list: { url: 'https://c.y.qq.com/v8/fcg-bin/fcg_myqq_toplist.fcg', params: () => { return { format: 'jsonp', g_tk: 5381, uin: 0, inCharset: 'utf-8', outCharset: 'utf-8', notice: 0, platform: 'h5', needNewCode: 1, _: new Date().getTime() } }, jsonp: 'jsonpCallback' } }
然后在 src\store 下新建 ApiService.js :
import Vue from 'vue' import API from '../config/api' function apiFactory(api) { //統一接口函數 return (id = null) => Vue.http.jsonp( api.url, { params: api.params(id), jsonp: api.jsonp } ) } export default { actions: { getRankList({}){ //'{}'也可以省略,查看Vuex官網教程,若需要用到store和commit就寫成'{state,commit}' return apiFactory(API.rank_list)() //最后的'()'是因為rank_list對象內有函數,向函數傳空參 } } }
接着,在 src\store 中新建 index.js :
import Vue from 'vue' import Vuex from 'vuex' import ApiService from './ApiService' Vue.use(Vuex) export default new Vuex.Store({ modules: { ApiService, } })
查看Vuex官網教程,由於我們后期用到的集中狀態較多,我們將store分成模塊,以免store對象很臃腫。
OK,到這里我們的后端數據獲取工作就可以啦。。
下面我們來編寫前端組件,我們將其命名為Rank.vue
先來一個 created生命周期鈎子,通過 this.$store.dispatch 獲取后端的數據:
created: function () { this.$store.dispatch('getRankList').then((response) => { //調用 ApiService.js 中 Actions:getRankList this.topList = response.data.data.topList }) }
可以先將 this.topList 通過 alert() 打印出來,查看返回數據的結構,再通過 v-for 將其呈現出來,具體的代碼實現參考項目源碼,這里針對其中的 CSS 幾個知識點着重講一下。
1.設置屏幕自適應。
只需要在App.vue中即可:
@media screen and (min-width: 68vh) { body { width: 68vh; //若屏幕寬度大於 68vh,取68vh margin: 0 auto; } }
2.元素定位

<div class="rank-media"> <img class="rankpic" v-lazy="rankItem.picUrl"> <div class="listen-count"> {{Math.round(rankItem.listenCount/1000) / 10 + '萬' }} </div> </div>
該段代碼呈現出的是上面左圖的效果,而我們想實現右圖的效果,讓數字跑到圖片的左下角。
細想 display: flex 實現不了我們想要的結果,但是 position: absolute 可以實現,設置為絕對定位的元素框從文檔流完全刪除,元素原先在正常文檔流中所占的空間會關閉,就好像該元素原來不存在一樣。然后,該元素會相對於其包含塊定位,若父元素為非static(默認)定位,則相對父元素,否則相對於根元素即html元素來定位。
此處, .listen-count 的父元素為 .rank-media ,給前者添加 position: absolute 的同時,必須給后者 添加 position: relative :
.rank-media { width: 100px; height: 100px; position: relative; //若去掉該行,.listen-count會相對body定位,達不到我們的目的 } .listen-count { position: absolute; font-size: 12px; color:white; bottom: 3px; left: 5px; }
3. 文本溢出處理

我們看到,由於 第一個歌曲的 歌名過長,導致內容超出了預想的范圍,不着急,給該元素加上如下 CSS 屬性:
white-space: nowrap //設置文本內容不換行

可是設置后,又發現 歌手名稱超出了界線,顯得頁面不美觀,只需給元素加如下 CSS 屬性:
overflow: hidden;
text-overflow: ellipsis; //溢出部分設置為 '...'
最終得到如下效果:

這樣即使文本溢出,也不會影響頁面的美觀了。
下一節我們分析重點頁面之一,src\components\RankPage.vue界面,即用戶點擊自己感興趣的排行榜之后,跳轉的頁面。
