项目简介

使用工具:

typeScript+vue3+setup语法糖+vite

大概:

主要实现的功能:

  1. 音乐查找及播放
  2. 轮播图
  3. 新歌速递
  4. 推荐专辑
  5. L显示热评

项目板块划分

头部 header 中间(核心)=左边+右边 底部footer

  • 发现音乐 FoundMusic

  • 轮播图 LunBoTu

  • 新歌速递 NewSongs

  • 推荐歌单 RecommendPlaylist

  • 搜索详情 Search

  • 音乐详情页 MusicDetail

开始实操

1.1项目初始化

axios文件夹http、pinia文件夹store、vue-router文件夹router、主要页面文件夹vies、element-plus、less

1.2项目布局

  1. app中放置组件==== 存放播放器
  2. 之中存放==
    ====
    ====
    ==
  3. Main>之中存放========

2.1 使用VERCEL部署网易云音乐api

image-20220526194248771

  1. 先使用github账号登陆vercel 链接
  2. 打开网易云api项目,点右上角fork 链接

image-20220526194349513

  1. 在vercel新建项目

  1. 选择网易云api

image-20220526194434359

  1. 名字自取,其他可以不改变,点击deploy
  1. image-20220526194456591

6.完成

image-20220526194510636

  1. 项目链接

3.1 搜索板块

  1. 先调用网易云 api
  2. 检查输入框是否有内容,添加回车事件获取关键词keyword
  3. 为列表添加点击事件,跳转到音乐详情页,并传入id参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const keyword = ref(' ');
let keylist = reactive(<any>[]);
const id = ref('11');
onMounted(async () => {
// 传入keyword给 api,并用keylist存贮 获取列表
const onSearch = async (id: any) => {
await SearchData(keyword.value)
.then((res) => {
console.log(res.data.result.songs);
keylist.splice(0);
keylist.push(res.data.result.songs);
})
.catch((err) => {
console.log(err);
});
};
//先检查输入框是否有内容,若果有则渲染到页面上
// 在设置回车事件,根据用户输入值更新页面
const myinput = document.querySelector(".serachInput") as HTMLInputElement;
keyword.value = myinput.value
onSearch(keyword.value);
myinput.addEventListener("keydown", function (e) {
if (e.key == "Enter") {
// 获取输入的值
// const serachInput = document.querySelector(".serachInput") as HTMLInputElement;
keyword.value = myinput.value;
console.log(id.value);
onSearch(keyword.value);
router.push('/Search')
}
});
})

3.2 音乐详情页

更新歌曲详情

  1. 接收传入的id参数
  2. 根据id调用api获取音乐详情
  3. 更新时间、歌词、歌手信息等

歌词

  1. 使用网易云api获取的歌词是入图的形式,需要手动将时间和歌词分离

  1. 调用api获取歌词,并将时间与歌词文字拆离

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const getgeci = () => {
    GetLyric(id).then((res) => {
    music.lyric = res.data.lrc.lyric
    let obj = {}
    let reg = /\[(.*?)](.*)/g;
    //使用正则表达式拆分
    music.lyric.replace(reg, (a, b, c) => {
    b = b.slice(0, 5)//时间取前4位便于计算
    obj[b] = c;
    })
    // a是原数据,b是时间,c是歌词
    geci2.value = obj;
    console.log("geci2", geci2.value);
    })
    1
    2
    3
    4
    5
    <div class="geci">
    <p class="lyric" v-for="(item, key, i) in geci2" :key="i">
    {{ item }}
    </p>
    </div>

    其中 ,item 是歌词 key是时间

  2. 实现歌词高亮

ontimeupdate 事件在视频/音频(audio/video)当前的播放位置发送改变时触发

1
2
3
4
5
6
7
8
9
10
const audio = document.querySelector('audio') as HTMLAudioElement;
audio.ontimeupdate = () => {
//将获取的时间转化成和歌词时间一样的格式
let time = transTime(audio.currentTime);
if (time in obj) {
righttime.value = time
console.log('success', righttime.value);
} else {
// console.log('erro');
}

==audio.currentTime==使用audio的currentTime属性获得当前的播放时间

用获取的时间与歌词列表里的时间匹配,并将匹配成攻的值赋给righttime

1
2
3
4
5
<div class="geci">
<p class="lyric" v-for="(item, key, i) in geci2" :key="i" :class="righttime == key ? 'highlight' : ' '">
{{ item }}
</p>
</div>

根据righttime 和 key值 的匹配结果 动态添加高亮样式。

  1. 歌词随播放时间滚动

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 歌词移动
    const lyricMove = () => {
    let highlight = document.getElementsByClassName('highlight')[0] as HTMLDivElement;
    const geci = document.querySelector(".geci") as HTMLDivElement;
    const gecihezi = document.querySelector(".gecihezi") as HTMLDivElement;
    if (highlight) {
    if (highlight.offsetTop >= 30) {
    // 单句歌词距离顶部的距离 > 30时,开始滚动
    gecihezi.scrollTop = highlight.offsetTop - 130
    }
    }
    }

项目中遇到的问题

  1. 使用官方推荐的获取url的方法时警告
1
2
3
<audio controls>
<source :src="` https://music.163.com/song/media/outer/url?id=${id}.mp3`">
</audio>

不影响实际项目运行!!

  1. vue3中的reactive响应式数据,不能直接复制
1
2
3
4
5
6
7
8
9
10
11
12
13
//方法一:使用ref定义
const a = ref({})
a.value=数组或对象;

//方法二:使用push()
const b=reactive([])
b.push(...数组)

//方法三:在reactive里面再封装一个{}
const c= reactive({
arr:[]
})
c.arr=数组或对象
  1. 不会处理ts产生的这种类型错误提醒(不影响项目运行)。