VUE项目实现音乐播放器(二)-------排行榜页面

今天,我们来实现播放器首页的 排行榜页面 的开发,也就是 src\components\Rank.vue ,效果截图:

排行榜页面

页面的图片、排行榜名称、歌曲等信息,来自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;   //溢出部分设置为 '...'

最终得到如下效果:

这样即使文本溢出,也不会影响页面的美观了。

猜你喜欢

转载自www.cnblogs.com/Fcode-/p/12556767.html