vue音樂項目歌手詳情頁小結

技術棧css

1,vue
2,vuex
3,vue-router(子路由)
需求分析html

1)歌手列表點擊歌手會跳轉到下級頁面歌手詳情頁,歌手詳情頁由四個部分組成vue

歌手圖片
返回按鈕:點擊返回歌手tab頁
隨機播放按鈕
歌手歌曲滾動
2)歌曲欄向上滾動到頂部時,圖片和播放按鈕隨之隱藏,保留歌手名和返回按鈕web

3)歌曲欄向下拖動時,歌手圖片的高度做出無縫增高vue-router

新的組件vuex

singer-detail.vue

music-list.vue

song-list.vue

 



實現
1.vuex 在介紹子路由的實現前咱們先來看vuexjson

這裏寫圖片描述
在src文件夾下新建一個store文件夾,該文件夾下有多個js文件api

actions.js涉及的異步操做

getters.js store中定義的getter

這裏返回state裏的singer

export const singer = state => state.singer

index.js 組裝模塊並導出

mutation.js 跟級別的mutation
//使用 ES2015 風格的計算屬性命名功能來使用一個常量做爲函數名
import * as types from './mutation-types'
const mutations = {
[types.SET_SINGER](state, singer) {
state.singer = singer
}
}
export default mutations

mutation-type.js 對mutation做相應的映射

state.js 定義store的state

 

 

1.子路由的實現
router文件夾下index.js配置歌手頁的子路由數組

{
path: '/singer',
component: Singer,
children: [
{
path: ':id',
component: SingerDetail
}
]
}

singer.vue中使用vue-router瀏覽器

<template>
<div class="singer" ref="singer">
<listview :data = "singers" @select="selectSinger"></listview>
<router-view></router-view>
</div>
</template>


歌手頁點擊歌手時singer.vue 中經過@select接受子組件傳遞來的singer屬性,@select="selectSinger"selectSinger方法根據singer.id實現子路由跳轉

selectSinger(singer) {
this.$router.push({
path: `/singer/${singer.id}`
})
this.setSinger(singer)
}

 


listview.vue歌手列表經過$emit方法傳遞出singer,這裏的item表明每一個singer

selectItem(item) {
this.$emit('select', item)
//console.log('item:' + item)
}

2.歌手詳情頁的實現

歌手詳情頁實現用瞭如下組件

<singer-detail>
<musci-list>
...
<scroll>
<song-list>...</song-list>
<loading>...</loading>
</scroll>
</music-list>
</singer-detail>

在Vue Devtools中能夠清晰看到模板的結構。
singer.vue下有兩個同級子組件分別爲singer-detail和list-view,其中singer-detail組件是經過路由來切換的。
singer-detail組件下有music-list組件,這是歌手詳情頁組件,該組件下有scroll組件,scroll組件實現滾動,scroll組件下的song-list組件是歌手歌曲列表組件,loading組件是優化組件,當歌手歌曲尚未獲取時顯示正在加載,從而提升用戶體驗。

數據的獲取與傳遞

歌手對應歌曲數據獲取
src/api/singer.js經過getSingerDetail方法獲取歌曲

export function getSingerDetail(singerId) {
const url = 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg'

const data = Object.assign({}, commonParams, {
hostUin: 0,
needNewCode: 0,
platform: 'yqq',
order: 'listen',
begin: 0,
num: 80,
songstatus: 1,
singermid: singerId
})

return jsonp(url, data, options)
}

 


在singer-detail.vue組件中寫了一個私有方法_getDetail用來獲取歌手數據,singer.vue的data屬性中維護了songs數組變量

data() {
return {
songs: []
  }
}
_getDetail() {
if (!this.singer.id) {
this.$router.push('/singer')
return
}
console.log(this.singer)
getSingerDetail(this.singer.id).then((res) => {
if (res.code === ERR_OK) {
console.log(res.data.list)
this.songs = this._normalizeSongs(res.data.list)
}
})
}

 

_getDetail方法中使用了_normalizeSongs方法對請求到的數據進行處理,由於jsonp請求返回到的數據不是咱們想要的,因此須要用此方法對數據進行處理。對請求返回到的數據返回一個songs數組,數組的每一個元素表明每一個song,其中song是一個類,這個類裏面保留着歌曲的相關信息,如歌曲id,歌手姓名等等。

這是一個音樂app,後面還會涉及到歌曲的處理,因此出於代碼可複用和可維護的角度來考慮,在common/js/song.js下建立了一個song Class,並建立了一個createSong工廠方法在傳入參數後直接返回一個new song

_normalizeSongs(list) {
let ret = []
list.forEach((item) => {
let {musicData} = item
if (musicData.songid && musicData.albummid) {
ret.push(createSong(musicData))
}
})
return ret
}

 



common/js/song.js

export default class Song {
constructor({id, mid, singer, name, album, duration, image, url}) {
this.id = id
this.mid = mid
this.singer = singer
this.name = name
this.album = album
this.duration = duration
this.image = image
this.url = url
}
}
export function createSong(musicData) {
return new Song({
id: musicData.songid,
mid: musicData.songmid,
singer: filterSinger(musicData.singer),
name: musicData.songname,
album: musicData.albumname,
duration: musicData.interval,
image: `https://y.gtimg.cn/music/photo_new/T002R300x300M000${musicData.albummid}.jpg?max_age=2592000`,
url: `http://ws.stream.qqmusic.qq.com/${musicData.songid}.m4a?fromtag=46`
})
}
function filterSinger(singer) {
let ret = []
if (!singer) {
return ''
}
singer.forEach((s) => {
ret.push(s.name)
})
return ret.join('/')
}

 


最後在singer-detail組件的created階段獲取數據

created() {
this._getDetail()
}

 


上面我介紹瞭如何獲取歌手詳情頁組件的相關數據,這些數據最終的目的是用來渲染的。

歌手圖片實現

在需求分析中提到的歌手圖片,這是一張寬高比爲10:7的圖片,咱們在以前的博文中提到了如何實現寬高比相等的圖片,這裏解決思路同樣
music-list.vue中stylus

.bg-image
position: relative
width: 100%
height: 0
padding-top: 70%
transform-origin: top
background-size: cover

 



歌手詳情頁歌手圖片,歌手名,返回和播放按鈕都是在music-list.vue中實現的(html,css),music-list下的子組件song-list維護了歌手歌曲列表。

點擊圖片返回效果實現,給按鈕添加點擊事件back

back() {
this.$router.back()
},

 


歌曲列表滾動效果實現

歌曲列表滾動效果使用了基礎組件scroll組件,這裏重點說明幾個關鍵點,滾動中特效的實現利用了CSS3 transform的translate3d和scale方法

向上滾動實現圖片隱藏效果
首先將scroll組件樣式overflow:hidden去掉
給圖片div層添加一個同級div class="bg-layer"
music-list組件data維護了scrollY並在watch中設置監聽,當scrollY發生改變時觸發相應事件

向下滾動實現圖片放大(transform:scale)

具體代碼重點scrollY

scrollY(newVal) {
let translateY = Math.max(this.minTransalteY, newVal)
let zIndex = 0
let scale = 1
let blur =0
const percent = Math.abs(newVal / this.imageHeight)
if (newVal > 0) {
scale = 1 + percent
zIndex = 10
} else {
blur = Math.min(20, percent * 20)
}
this.$refs.layer.style[transform] = `translate3d(0,${translateY}px,0)`
this.$refs.filter.style[backdrop] = `blur(${blur}px)`
if (newVal < this.minTransalteY) {
zIndex = 10
this.$refs.bgImage.style.paddingTop = 0
this.$refs.bgImage.style.height = `${RESERVED_HEIGHT}px`
this.$refs.playBtn.style.display = "none"
} else {
this.$refs.bgImage.style.paddingTop = '70%'
this.$refs.bgImage.style.height = 0
this.$refs.playBtn.style.display = ''
}
this.$refs.bgImage.style[transform] = `scale(${scale})`
this.$refs.bgImage.style.zIndex = zIndex
}

CSS3transform屬性瀏覽器兼容處理

let elementStyle = document.createElement('div').style

let vendor = (() => {
let transformNames = {
webkit: 'webkitTransform',
Moz: 'MozTransform',
O: 'OTransform',
ms: 'msTransform',
standard: 'transform'
}

for (let key in transformNames) {
if (elementStyle[transformNames[key]] !== undefined) {
return key
}
}

return false
})()

export function prefixStyle(style) {
if (vendor === false) {
return false
}

if (vendor === 'standard') {
return style
}

return vendor + style.charAt(0).toUpperCase() + style.substr(1)
}

 

調測反思
在項目調測過程當中,咱們要結合Vue Devtools,好比咱們在得到歌曲數組時在singer-detail中console.log(this.songs)會發現沒法看到具體內容

但在Vue Devtools中的singer-detail.vue組件的data中能夠很清楚的看到songs數組

總結

子路由使用滾動處理邊界處理瀏覽器兼容性代碼複用和可維護性

相關文章
相關標籤/搜索