【Vue知识点- No8.】网易云音乐案例(vant组件库的使用)

No8.网易云音乐案例

知识点自测

  • 知道reset.css和flexible.js的作用。
  • 什么是组件库-例如bootstrap的作用。
  • yarn命令的使用。
  • 组件名字用name属性方式注册。
  • 如何自定义组件库样式。

1.本地接口项目部署

在这里插入图片描述

下载网易云音乐node接口项目, 在本地启动, 为我们vue项目提供数据支持。
项目地址
备用地址
下载git clone [email protected]:Binaryify/NeteaseCloudMusicApi.git
下载后, 安装所有依赖: npm install 或者 yarn,
在本地启动起来: node app.js 不能使用npm run serve启动,因为这不是vue的脚手架项目,
测试访问此地址是否有数据:http://localhost:3000, 看到如下页面就成功了。
在这里插入图片描述
在这里插入图片描述
总结: Node搭建的服务,如何把数据请求回来?前端请求本地的node项目, 收到请求后,node服务器伪装请求去拿网易云音乐服务器数据转发回给自己前端。(如何做反向代理解决跨域问题?本地node服务器开启cors,负责请求的转发和数据接收回传。)

学习目标

1.能够掌握vant组件库的使用。
2.能够掌握vant组件自定义样式能力。
3.能够掌握组件库使用和文档使用能力。
4.能够完成网易云音乐案例。

2.前端项目准备

2-1. 前端项目初始化

目标: 初始化项目, 下载必备包, 引入初始文件, 配置按需自动引入vant, 创建页面组件。
1》初始化工程:vue create music-demo
2》下载需要的所有第三方依赖包:yarn add axios vant vue-router
3》下载Vant自动按需引入插件:yarn add babel-plugin-import -D

4》在babel.config.js配置–看Vant文档。

plugins: [
    ['import', {
   
        libraryName: 'vant',
        libraryDirectory: 'es',
        style: true
    }, 'vant']
]

5》引入笔记代码里准备好的reset.css和flexible.js - 实现样式初始化和适配问题 - 引入到main.js中

import "@/mobile/flexible" // 适配
import "@/styles/reset.css" // 初始化样式

2-2. 需求分析

根据需求, 创建路由所需要的5个页面的组件:

  • Layout(布局, 顶部导航和底部导航) > 二级路由 Home 、Search和Play。
布局图

在这里插入图片描述

创建需要的views下的页面组件4个:

  • src/views/Layout/index.vue - 负责布局(上下导航 - 中间二级路由切换首页和搜索页面)
<style scoped>
/* 中间内容区域 - 容器样式(留好上下导航所占位置) */
.main {
   
  padding-top: 46px;
  padding-bottom: 50px;
}
</style>
  • views/Home/index.vue - 标题和歌名样式
/* 标题 */
.title {
   
  padding: 0.266667rem 0.24rem;
  margin: 0 0 0.24rem 0;
  background-color: #eee;
  color: #333;
  font-size: 15px;
}
/* 推荐歌单 - 歌名 */
.song_name {
   
  font-size: 0.346667rem;
  padding: 0 0.08rem;
  margin-bottom: 0.266667rem;
  word-break: break-all;
  text-overflow: ellipsis;
  display: -webkit-box; /** 对象作为伸缩盒子模型显示 **/
  -webkit-box-orient: vertical; /** 设置或检索伸缩盒对象的子元素的排列方式 **/
  -webkit-line-clamp: 2; /** 显示的行数 **/
  overflow: hidden; /** 隐藏超出的内容 **/
}
  • views/Search/index.vue
/* 搜索容器的样式 */
.search_wrap {
   
  padding: 0.266667rem;
}

/*热门搜索文字标题样式 */
.hot_title {
   
  font-size: 0.32rem;
  color: #666;
}

/* 热搜词_容器 */
.hot_name_wrap {
   
  margin: 0.266667rem 0;
}

/* 热搜词_样式 */
.hot_item {
   
  display: inline-block;
  height: 0.853333rem;
  margin-right: 0.213333rem;
  margin-bottom: 0.213333rem;
  padding: 0 0.373333rem;
  font-size: 0.373333rem;
  line-height: 0.853333rem;
  color: #333;
  border-color: #d3d4da;
  border-radius: 0.853333rem;
  border: 1px solid #d3d4da;
}
  • views/Play/index.vue - 直接从预习资料里复制(节省时间) - 可自己扩展阅读代码
<template>
  <div class="play">
    <!-- 模糊背景(靠样式设置), 固定定位 -->
    <div
      class="song-bg"
      :style="`background-image: url(${
     
        songInfo && songInfo.al && songInfo.al.picUrl
      }?imageView&thumbnail=360y360&quality=75&tostatic=0);`"
    ></div>
    <!-- 播放页头部导航 -->
    <div class="header">
      <van-icon
        name="arrow-left"
        size="20"
        class="left-incon"
        @click="$router.back()"
      />
    </div>
    <!-- 留声机 - 容器 -->
    <div class="song-wrapper">
      <!-- 留声机本身(靠css动画做旋转) -->
      <div
        class="song-turn ani"
        :style="`animation-play-state:${playState ? 'running' : 'paused'}`"
      >
        <div class="song-img">
          <!-- &&写法是为了防止报错, 有字段再继续往下访问属性 -->
          <img
            style="width: 100%"
            :src="`${
     
              songInfo && songInfo.al && songInfo.al.picUrl
            }?imageView&thumbnail=360y360&quality=75&tostatic=0`"
            alt=""
          />
        </div>
      </div>
      <!-- 播放按钮 -->
      <div class="start-box" @click="audioStart">
        <span class="song-start" v-show="!playState"></span>
      </div>
      <!-- 播放歌词容器 -->
      <div class="song-msg">
        <!-- 歌曲名 -->
        <h2 class="m-song-h2">
          <span class="m-song-sname"
            >{
   {
    songInfo.name }}-{
   {
   
              songInfo && songInfo.ar && songInfo.ar[0].name
            }}</span
          >
        </h2>
        <!-- 歌词部分-随着时间切换展示一句歌词 -->
        <div class="lrcContent">
          <p class="lrc">{
   {
    curLyric }}</p>
        </div>
      </div>
      <!-- 留声机 - 唱臂 -->
      <div class="needle" :style="`transform: rotate(${needleDeg});`"></div>
    </div>
    <!-- 播放音乐真正的标签
      看接口文档: 音乐地址需要带id去获取(但是有的歌曲可能404)
      https://binaryify.github.io/NeteaseCloudMusicApi/#/?id=%e8%8e%b7%e5%8f%96%e9%9f%b3%e4%b9%90-url
     -->
    <audio
      ref="audio"
      preload="true"
      :src="`https://music.163.com/song/media/outer/url?id=${id}.mp3`"
    ></audio>
  </div>
</template>

<script>
// 获取歌曲详情和 歌曲的歌词接口
import {
    getSongByIdAPI, getLyricByIdAPI } from '@/api'
import {
    Icon } from 'vant'
export default {
   
  components: {
   
    [Icon.name]: Icon,
  },
  name: 'play',
  data() {
   
    return {
   
      playState: false, // 音乐播放状态(true暂停, false播放)
      id: this.$route.query.id, // 上一页传过来的音乐id
      songInfo: {
   }, // 歌曲信息
      lyric: {
   }, // 歌词枚举对象(需要在js拿到歌词写代码处理后, 按照格式保存到这个对象)
      curLyric: '', // 当前显示哪句歌词
      lastLy: '' // 记录当前播放歌词
    }
  },
  computed: {
   
    needleDeg() {
    // 留声机-唱臂的位置属性
      return this.playState ? '-7deg' : '-38deg'
    }
  },
  methods: {
   
    async getSong() {
    // 获取歌曲详情, 和歌词方法
      const res = await getSongByIdAPI(this.id)
      this.songInfo = res.data.songs[0]
      // 获取-并调用_formatLyr方法, 处理歌词
      const lyrContent = await getLyricByIdAPI(this.id)
      const lyricStr = lyrContent.data.lrc.lyric
      this.lyric = this._formatLyr(lyricStr)
      // 初始化完毕先显示零秒歌词
      this.curLyric = this.lyric[0]
    },
    _formatLyr(lyricStr) {
   
      // 可以看network观察歌词数据是一个大字符串, 进行拆分.
      let reg = /\[.+?\]/g // 
      let timeArr = lyricStr.match(reg) // 匹配所有[]字符串以及里面的一切内容, 返回数组
      console.log(timeArr); // ["[00:00.000]", "[00:01.000]", ......]
      let contentArr = lyricStr.split(/\[.+?\]/).slice(1) // 按照[]拆分歌词字符串, 返回一个数组(下标为0位置元素不要,后面的留下所以截取)
      console.log(contentArr);
      let lyricObj = {
   } // 保存歌词的对象, key是秒, value是显示的歌词
      timeArr.forEach((item, index) => {
   
        // 拆分[00:00.000]这个格式字符串, 把分钟数字取出, 转换成秒
        let ms = item.split(':')[0].split('')[2] * 60
        // 拆分[00:00.000]这个格式字符串, 把十位的秒拿出来, 如果是0, 去拿下一位数字, 否则直接用2位的值
        let ss = item.split(':')[1].split('.')[0].split('')[0] === '0' ? item.split(':'
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值