github:https://github.com/Ching-Lee/vue-music
1.分析后台数据
从QQ音乐网页版获取后台数据
这里的回掉函数是callback
-
创建歌手页面的请求文件
import jsonp from '../assets/js/jsonp'
import {commonParams, optionsPc} from './config'
export default function getSingerList () {
const url = 'https://u.y.qq.com/cgi-bin/musicu.fcg'
const data = {
'comm': {
'ct': 24,
'cv': 10000
},
'singerList': {
'module': 'Music.SingerListServer',
'method': 'get_singer_list',
'param': {
'area': -100,
'sex': -100,
'genre': -100,
'index': -100,
'sin': 0,
'cur_page': 1
}
}
}
// 实现将多个对象拷贝到同一个对象中
const param = Object.assign({}, commonParams,
{
loginUin: 0,
hostUin: 0,
format: 'jsonp',
platform: 'yqq',
needNewCode: 0,
data: JSON.stringify(data)
})
// 返回值就是promise
return jsonp(url, param, optionsPc)
}
- 在config.js中一些参数做了改变
// 配置通用参数
export const commonParams = {
g_tk: 5381,
inCharset: 'utf-8',
outCharset: 'utf-8',
notice: 0
}
// 配置jsonp库的通用的options
export const options = {
// 通过qq得到了回掉函数的参数名
param: 'jsonpCallback'
}
// PC端的回掉函数
export const optionsPc = {
// 通过qq得到了回掉函数的参数名
param: 'callback'
}
- singer.vue组件中获取数据
- 在singer.vue中调用该组件
3.图片懒加载
我们现在是一次性加载所有的图片,会影响性能,这里应该使用图片懒加载
安装vue-lazyload插件
在main.js中引入vue.lazyload
import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad, {
loading:require('./assets/images/music_logo.png')
})
就会进行首屏加载,之后滚动到要显示的地方会再加载。
在listveiw中更改,使用v-lazy标签
-
{{item.name}}
4.正在载入loading组件
{{title}}
在歌手组件中调用loading组件,使用v-show,在列表没有长度的时候显示,有长度不显示
5.快速导航入口
- 首先添加计算属性,获取到所有城市的名称:
computed: {
shortcutList () {
let keylist = []
for (let key in this.data) {
if (key) {
keylist.push(key)
}
}
return keylist
}
},
- 在template中添加快速入口的div
-
{{key}}
mounted () {
this.$nextTick(function () {
this.citylist = this.$refs.roll.children
this.headerHeight = this.citylist[0].offsetTop
this.quicknavlist = this.$refs.quickNav.children
this.scrollListener()
})
},
整个ul使用了固定定位。
- 可以看到给ul注册了点击事件,使用了事件委托的原理。
- scrollTo的意思就是把传入参数的x,y坐标移动到浏览器(0,0)点。
- offsetLeft 和 offsetTop 返回的是相对于 offsetParent 元素的距离,而 offsetParent 指的是一个元素最近的父级定位元素,如果没有定位元素就是文档根节点。所以会超出视窗
点击了之后通过event.target拿到被点击元素的li,获取到data-index属性,然后去遍历左边的城市大的li,如果这个li的索引和data-index相同,就去计算出当前这个li距离可视窗口顶部的距离,然后减去头部和导航栏的距离,就是让这个计算出的高度滚动到(0,0)点。
methods: {
onShortcutTouchStart (event) {
// 点击的快速入口的li
let current = event.target
// 拿到点击的索引
let index = current.getAttribute('data-index')
// 遍历各个城市的li(每个li里面嵌套了title和ul(里面是该城市的歌手))
for (let liIndex in this.citylist) {
// 如果点击的这个快速入口的索引和
if (liIndex === index) {
let height = this.citylist[liIndex].offsetTop - this.headerHeight
window.scrollTo(0, height)
}
}
},
- 之后我们添加一个滚动监听事件,看各个城市的标题出现在屏幕中,我们就让快速导航栏颜色变白,同时他的前一个或者后一个如果是白的,就让他变黑并break。
这里用到了事件节流
scrollListener () {
let _self = this
let timeout
window.addEventListener('scroll', function () {
if (timeout) {
clearTimeout(timeout)
}
// 事件节流
timeout = setTimeout(callback(_self), 100)
})
function callback (_self) {
for (let index = 0; index < _self.citylist.length; index++) {
// 把标题那一行给拿出来,h2
let title = _self.citylist[index].getElementsByTagName('h2')[0]
let titleTop = title.offsetTop - (document.body.scrollTop || document.documentElement.scrollTop)
let currentli = _self.quicknavlist[index]
if (currentli) {
if (titleTop >= _self.headerHeight && titleTop <= document.documentElement.clientHeight) {
currentli.style.color = 'white'
if (_self.quicknavlist[index - 1].style.color === 'white') {
_self.quicknavlist[index - 1].style.color = 'black'
}
if (_self.quicknavlist[index + 1].style.color === 'white') {
_self.quicknavlist[index + 1].style.color = 'black'
}
break
}
}
}
}
},