1

在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

这个组件需求:

  1. 背景图 bgImage
  2. 标题title
  3. 歌手详情数据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)
    },
}

云深不知处
431 声望10 粉丝