VUE练手项目实现音乐播放器(二)-------排行榜组件
今天,我们来实现播放器首页的 排行榜页面 的开发,也就是 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界面,即用户点击自己感兴趣的排行榜之后,跳转的页面。