在singer.vue中,点击某一歌手,根据路由跳转到singer-detail.vue在vue-muscie:singer.vue页面的5.数据序列化后传入list-vue中相关逻辑
selectSinger(singer) {
//导航至singer-detail.vue页面
this.$router.push({
path: `/singer/${singer.id}`
})
//同时,将singer的信息放入vuex中
this.setSinger(singer)
},
由于singer-detail.vue页面具有共同性,因此封装成一个组件music-list.vue
1.singer-detail.vue
这个组件比较简单,一个壳子,获取数据传入组件
1.1获取数据
_getDetail() {
//如果在歌手详情页面刷新,无法获取singer.id,则直接返回歌手列表页面
if (!this.singer.id) {
this.$router.push('/singer')
}
getSingerDetail(this.singer.id).then((res) => {
if (res.code === ERR_OK) {
this.songs = this._normallizeSongs(res.data.list)
}
})
},
1.2 获取的数据序列化
_normallizeSongs(list) {
let ret = []
list.forEach((item) => {
let {musicData} = item
if (musicData.songid && musicData.albummid) {
ret.push(createSong(musicData))
}
})
return ret
}
这里使用createSong,创建一个song实例
2.music-list.vue
这个组件需求:
- 背景图 bgImage
- 标题title
- 歌手详情数据songs
2.1 页面
组件需要接收的数据props
props: {
bgImage: { //背景图片
type: String,
default: ''
},
songs: { //歌手详情数据songs
type: Array,
default: () => []
},
title: { //标题title
type: String,
default: ''
},
}
背景图片的利用:style 和 computed
<div class="bg-image" :style="bgStyle" ref="bgImage">
computed: {
bgStyle() {
return `background-image:url(${this.bgImage})`
}
},
2.2 滚动列表
根据歌手查询到歌曲列表,需要滚动scroll.vue
<div class="bg-layer" ref="layer"></div>
<scroll
@scroll="scroll" //需要派发滚动位置,触发的事件
:probe-type="probeType" //不需要截流
:listen-scroll="listenScroll" //派发滚动位置
:data="songs" //接收数据,初始化scroll
class="list"
ref="list">
<div class="song-list-wrapper">
<song-list @select="selectItem" :songs="songs" :rank="rank"></song-list>
</div>
</scroll>
2.3 滚动需求
- 为了能让他向上滚动,初始化的时候列表设置top值
mounted() {
//背景图图片的高度
this.imageHeight = this.$refs.bgImage.clientHeight
//滚动的边界:滚动到此 背景图片 ——(减去) 顶部title的高度
this.minTranslateY = -this.imageHeight + RESERVED_HEIGHT(40)
//初始化的时候列表设置top值:为了列表向上滚动而进行traslate3d
this.$refs.list.$el.style.top = `${this.$refs.bgImage.clientHeight}px`
},
- 左侧滚动
触发滚动事件
scroll(pos) {
this.scrollY = pos.y
},
监听滚动位置scrollY
watch: {
scrollY(newY) {
//往上滑动newY是负数 translateY往上移动是负数
//没有滑到临界值的时候translateY=newY 滑动顶部40的时候translateY=this.minTranslateY
let translateY = Math.max(this.minTranslateY, newY)
this.$refs.layer.style['transform'] = `translate3d(0, ${translateY}px,0)`
this.$refs.layer.style['webkitTransform'] = `translate3d(0, ${translateY}px,0)`
let zIndex = 0
//缩放
let scale = 1
//比例
let perscent = Math.abs(newY / this.imageHeight)
//高斯模糊
let blur = 0
//下拉的时候
if (newY > 0) {
scale = 1 + perscent
zIndex = 10
} else {
//上滑的时候:高斯模糊
blur = Math.min(20 * perscent, 20)
}
if (newY < this.minTranslateY) {
//上滑 `过` 临界值的时候,背景图片相应改变,按钮消失
zIndex = 10
this.$refs.bgImage.style.paddingTop = 0
this.$refs.bgImage.style.height = `${RESERVED_HEIGHT}px`
this.$refs.playButton.style.display = 'none'
} else {
//下滑 `未过` 临界值的时候
this.$refs.bgImage.style.paddingTop = '70%'
this.$refs.bgImage.style.height = '0'
this.$refs.playButton.style.display = ''
}
this.$refs.bgImage.style.zIndex = zIndex
//为什么从顶部显示scale缩放:因为下面的CSS .bg-image中 transform-origin: top
//下拉的时候放大效果
this.$refs.bgImage.style[transform] = `scale(${scale})`
//高斯模糊 IOS
this.$refs.bgImage.style[backdrop] = `blur(${blur}px)`
}
},
3.浏览器前缀
在使用transform以及back-drop的时候,需要根绝浏览器添加一些前缀,封装成方法调用
let elementStyle = document.createElement('div').style
//自执行函数:浏览器兼容的前缀
let vender = (() => {
const tranforNames = {
webkit:'webkitTransfrom',
Moz:'MozTransfrom',
O:'OTransfrom',
ms:'msTransfrom',
standard:'standard'
}
for(let key in transforNames){
if(elementStyle[transfromNames[key]] !== undefined){
return key
}
}
return false
})()
export function prefixStyle(style){
if(vendor === false){
return false
}
if(ventor === 'standard'){
return style
}
return vendor + style.charAt(0).toUpperCase() + style.substr(1)
}
在music-list.vue中引入
const transform = prefixStyle('transform')
4.song-list.vue
列表很常见,封装成组件song-list.vue
传入songs数据
功能:展示数据,传出点击的数据
<div class="song-list">
<ul>
<li @click="selectItem(song,index)" :key="song.id" v-for="(song,index) in songs" class="item">
<div class="content">
<h2 class="name">{{song.name}}</h2>
<p class="desc">{{getDesc(song)}}</p>
</div>
</li>
</ul>
</div>
methods:{
getDesc(song) {
return `${song.singer} . ${song.album}`
},
selectItem(item, index) {
this.$emit('select', item, index)
},
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。