1.Vue3实战——网易云音乐

Vue3实战—网易云音乐

效果展示

在这里插入图片描述

参考资料

Vue2_网易云音乐项目_哔哩哔哩_bilibili

14_项目_网络请求封装_哔哩哔哩_bilibili

Vant 4 - 轻量、可定制的移动端组件库 (vant-ui.github.io)

Interactive CSS Grid Generator | Layoutit Grid

Flex 布局语法教程 | 菜鸟教程 (runoob.com)

CSS代码调试_哔哩哔哩_bilibili

视频转gif - 在线工具 (tool.lu)

不要太屌丝,奋斗,有点精气神!!

不要把别人当傻子,也不要觉得自己很聪明,这都是缺乏存在感,野心存于胸,去做。这几年,他肯已经成熟进步,不要原地踏步,越颓废越丧。用时间去做自己的事情。你要一头扎进去。静下心来。去试试看看有没有错。

自己注意力的本质是身体的内核核心,要有不断的能量补充进去。

需求&技术栈&项目分析

1.如何开始构思一个项目?

1.需求分析
2.技术栈选择(新手会什么用什么即可)
3.项目结构设计:设计组件和路由
4.界面设计
5.开始开发

实际开发,大致看一下教程,先找到具备的【功能】;
然后看一下技术,用到了哪些
最后规划一下大致组件设计【可以使用什么画图工具啥的】
记住【一个优秀的程序员,架构时间永远比敲代码时间长, 一直敲的都是新手,合理选择技术栈】

2.网易云音乐的构思思路

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

组件命名

1.需求/功能分析(组件用【】表示)
	一共3个页面和一个布局容器【Layout】放下面和上面的路由导航以及中间的页面
    Layout
    	配置对应路由
    推荐页
    	【Recommended playlist】
        【The latest music】
         	【Song details】
            	【Song review】
    热歌榜页
    	【Popular song ranking】
    搜索页
		【Search】
2.技术栈就用最新的那套:vant+axios+scss(super css)+vue3
3.项目结构设计
	路由:
    	Recommendation page	
        Hit song list page
        Search page
        xxx[]——>Song details:router-link[paramas] to details useRoute
4.

3.后台接口启动

  1. 拿到接口地址

在这里插入图片描述

  1. 去下载该后台项目
  2. 配置node启动后台接口

项目结构设计

D:\课程\2024学习\前端项目\网易云音乐\01_笔记和ppt 相关笔记参考

D:\源码\OutCode\学习代码\黑马Vue\my-music

1.准备工作:创建项目,安装vant+axios+router,配置axios 【体力活】
2.创建页面【参考设计阶段命名】
3.布局页面
4.封装请求
5.获取后台数据
6.完成业务开发

0.VueStart

Vue工程搭建有很多【体力活】重复部分,因此将此划分为通用部分。
	1.必备插件:scss,router,axios,pinia
				pnpm  i scss  vue-router axios pinia 
    2.	import xxx  from xx  
		vueUse()

1.style.css

Vue官方做的响应式设计
	1.流式宽高
	2.媒体查询
#app {
  max-width: 1280px;
  margin: 0 auto;
  padding: 2rem;
  text-align: center;
}

@media (prefers-color-scheme: light) {
  :root {
    color: #213547;
    background-color: #ffffff;
  }
  a:hover {
    color: #747bff;
  }
  button {
    background-color: #f9f9f9;
  }
}

2.router.js

import { createRouter, createWebHistory } from "vue-router";
const routes = [
    {
        path: "/",
        name: "Home",
        component: () => import("../views/Home.vue"),
    },
    {
        path: "/detail/:id",
        name: "detail",
        component: () => import("../views/SingleDetails.vue"),
        props: true

    }
];

const router = createRouter({
    history: createWebHistory(),
    routes
});

export default router;

3.pinia.js

import { createPinia } from 'pinia'
const pinia = createPinia()

import { defineStore } from 'pinia'


export const useTestStore = defineStore('testStore', {
  state: () => {
    return {
      count: 0
    }
  },
  actions: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    }
  },
  getters: {
    doubleCount(state) {
      return state.count * 2
    }
  }
})

4.vite.config.js @路径配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': '/src',
    },
  },
 
})

1.Vant组件库

Vant 4 - 轻量、可定制的移动端组件库 (vant-ui.github.io)

1.安装 pnpm i vant
2.引入注册【一次性注册所有组件】
	import Vant from 'vant';
    import { createApp } from 'vue';
	import 'vant/lib/index.css';

    const app = createApp();

    app.use(Vant);

    // Lazyload 指令需要单独进行注册
    app.use(vant.Lazyload);

3.使用
	弹出框的函数调用

定制主题

关于样式穿透,样式使用专题。

2.封装请求

//1.封装请求
import axios from 'axios'
const instance = axios.create({
  baseURL: 'http://localhost:3000',
  timeout: 10000
})
export default instance
//2.写API接口
import request from '../utils/request'
export const RecommendMusic = (params) => {
  return request({
    url: '/personalized',
    method: 'GET',
    params:params
  })
}

export const NewSong = (params) => {
  return request({
    url: '/personalized/newsong',
    method: 'GET',
    params:params
  })
}

//3.统一管理API
import { RecommendMusic,NewSong } from "./RecommendationPage";
import { Search,SearchHot } from "./SearchPage";
import {getMusicDetails} from './details'

export const RecommendMusicAPI = RecommendMusic
export const NewSongAPI = NewSong
export const SearchAPI = Search
export const SearchHotAPI = SearchHot
export const getMusicDetailsAPI = getMusicDetails

3.Layout

NavBar
Tabbar

易错问题:router-view来管理页面就统一用router-view管理,不要使用组件导入,不然会出现重复现象。
比如app.vue
应该这样
<script setup>
import { ref } from 'vue'

</script>

<template>
  <div class="container">
    <router-view></router-view>
  </div>
</template>

<style lang="scss" scoped>

</style>
不要使用 <Layout></Layout>

Layout.vue

<script setup>
import { ref,watchEffect,computed} from 'vue'
import {useRoute} from 'vue-router'
const active = ref(0);

const route = useRoute();
const title = ref('首页');

const changeTitle=watchEffect(()=>{
  if(active.value==0) title.value='首页';
  if(active.value==1) title.value='搜索';
})
</script>

<template>
 <van-nav-bar :title=title />
 <RouterView />

 <van-tabbar v-model="active" >  
  <van-tabbar-item icon="home-o" to="/recommend">推荐歌曲</van-tabbar-item>
  <van-tabbar-item icon="search" to="/search">搜索</van-tabbar-item>
  
</van-tabbar>
</template>

<style lang="scss" scoped>

</style>

路由配置

import { createRouter, createWebHistory } from "vue-router";
const routes = [
    {
        path: "/",
        name: "Layout",
        component: () => import("../views/Layout.vue"),
        children: [
            {
                path: "recommend",
                name: "Recommend",
                component: () => import("../views/RecommendationPage.vue")
            },
            {
                path: "search",
                name: "Search",
                component: () => import("../views/SearchPage.vue")
            },
            
        ]
    }

];

const router = createRouter({
    history: createWebHistory(),
    routes
});

export default router;

RecommendationPage

1.基本样式布局

<script setup>

</script>

<template>
  <p class="title">推荐歌单</p>
  <van-row gutter="10">
    <van-col span="8">
      <van-image width="100%" height="100" src="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" />
      <p class="song_name">[歌单1] 热门推荐</p>
    </van-col>
    <van-col span="8">
      <van-image width="100%" height="100" src="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" />
    </van-col>
    <van-col span="8">
      <van-image width="100%" height="100" src="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" />
    </van-col>

  </van-row>

</template>

<style lang="scss" scoped>
/* 标题 */
.title {
  padding: 0.4rem 0.24rem;
  margin: 0 0 0.4rem 0;
  background-color: #eee;
  color: #333;
  font-size: 15px;
}

/* 推荐歌单 - 歌名 */
.song_name {
  font-size: 0.6rem;
  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;
  /** 隐藏超出的内容 **/
}
</style>

2.后台数据

C:\Users\23599\Desktop\小满学习笔记\code\Vue3实战\网易云音乐本地接口

网易云音乐 NodeJS 版 API (binaryify.github.io)

pnpm install
node app.js

http://localhost:3000/personalized?limit=6

3.封装Axios

1.request.js
import axios from 'axios'


const instance = axios.create({
  baseURL: 'http://localhost:3000',
  timeout: 10000
})


export default instance
2.API-RecommendationPage.js
import request from '../utils/request'

export const RecommendMusic = () => {
  return request({
    url: '/personalized',
    method: 'GET',
    params:params
  })
}
3.API-index.js
import { RecommendMusic } from "./RecommendationPage";

export const RecommendMusicAPI = RecommendMusic

4.使用&渲染

<script setup>
import { RecommendMusicAPI } from "@/API/index";
import { onMounted, ref } from 'vue';

const recommendList = ref([])

onMounted(
  async () => {
    const res = await RecommendMusicAPI({ limit: 6 })
    console.log(res.data.result);
    recommendList.value = res.data.result
  })

</script>

在这里插入图片描述

 <p class="title">推荐歌单</p>
  <van-row gutter="10">
    <van-col span="8" v-for="(item, index) in recommendList" :key="index">
      <van-image width="100%" height="100" :src="item.picUrl" />
      <p class="song_name">{{item.name}}</p>
    </van-col>
  </van-row>

最新歌单

单元格组件【title,right-icon】

//onMounted 里面只能放一个回调函数,放2个不行的哦!
onMounted (
 
  async () => {
    const res = await RecommendMusicAPI({ limit: 6 })
    console.log('请求成功');
    recommendList.value = res.data.result
  }
 
)

定制主题样式

常见问题 - Vant 4 (vant-ui.github.io)

ConfigProvider 全局配置 - Vant 4 (vant-ui.github.io)

//深色模式
const theme = ref('none')
const Darkfn=()=>{
  theme.value='dark'
}
<van-button type="primary" @click="Darkfn()">开启深色模式</van-button>
  <van-config-provider :theme="theme" ></van-config-provider>

修复下面bar挡住的原因

在这里插入图片描述

SongItem.vue

通过router.query传递多个参数

<script setup>
import { ref, defineProps } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const props = defineProps({
  item: {
    type: Object,
  }
})
const GoToPlayer = (id, name, artist) => {
  console.log(id, name, artist)
  router.push({
    name: 'player',
    query: { id: id, name: name, artist: artist }
  })

}
</script>

<template>
  <van-cell :title="item.name" :label="item.song.artists[0].name"
    @click="GoToPlayer(item.id, item.name, item.song.artists[0].name)">
    <template #right-icon>
      <van-icon name="play-circle-o" size="1.5rem" class="icon" />
    </template>
  </van-cell>
</template>

<style lang="scss" scoped></style>

//使用
<SongItem v-for="(item, index) in newSongList" :key="index" :item="item"></SongItem>
  

Player.vue

1.接收基本数据
//接口报错问题
export const  getMusicDetails= (id) => {
  return request({
    url: '/song/url',
    method: 'get',
    params :{id}  //对象,且字段和后端接口参数一致
  })
}

在这里插入图片描述

在这里插入图片描述

<script setup>
import { defineProps, onMounted, ref } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
const id = route.query.id;
const name = route.query.name;
const artist = route.query.artist;

</script>

<template>
  <h1>Player</h1>
  <p>id: {{ id }}</p>
  <p>name: {{ name }}</p>
  <p>artist: {{ artist }}</p>
  
</template>

<style lang="scss" scoped></style>

2.书写样式并播放音乐

使用uniapp + Vue3 + uni.createInnerAudioContext()实现播放歌曲及歌词滚动、拖动进度条_vue音乐播放器歌词滚动-CSDN博客

Vue音乐播放器组件

音乐样式-————CV工程师

1.旋转播放

2.暂停,开始动画
//这个样式和播放得有专门的css来写
Song details:router-link[paramas] to details & useRoute
音乐播放/暂停
	获取音乐并控制播放
    css旋转样式,当播放时,改flag,flag动时样式触发即可
歌词
	歌词效果
    歌词前进效果
button
	打开
    下载

Search page

在这里插入图片描述

search input 
	获取input内容,和后台数据进行匹配  input.value————return getValue.渲染;
hot search 
	简单的调接口渲染
Search history
	input.value————arr.push()———render()

搜索结果&热门搜索数据铺陈

<script setup>
import { onMounted, ref } from 'vue';
import { SearchAPI, SearchHotAPI } from '../API/index';
const inputValue = ref('');
const searchList = ref([]);
const searchHotList = ref([]);
onMounted(
  async () => {


    // 热门搜索接口
    const searchHotResult = await SearchHotAPI();
    searchHotList.value = searchHotResult.data.result.hots;

  }
)
const onSearch = async () => {
  console.log(inputValue.value);
  if (inputValue.value) {
    const searchResult = await SearchAPI({ keywords: inputValue.value, limit: 10 });
    searchList.value = searchResult.data.result.songs;
    console.log(searchList.value);
    console.log('搜索成功');
    inputValue.value = '';

  }
}
const onHotSearch = (keywords) => {
  inputValue.value = keywords;
  onSearch();
}
</script>

<template>
  <van-search v-model="inputValue" placeholder="请输入搜索关键词" shape="round" @search="onSearch" />
  <div class="hotMusic">
    <h4>热门搜索</h4>
    <van-button style="margin-right: 10px;" v-for="item in searchHotList" type="default" size="small"
      @click="onHotSearch(item.first)">{{ item.first }}</van-button>
  </div>
  <h4>最佳匹配</h4>
  <van-cell :title="item.name" v-for="(item, index) in searchList" :key="index" :label="item.artists[0].name">
    <template #right-icon>
      <van-icon name="play-circle-o" size="1.5rem" class="icon" />
    </template>
  </van-cell>
</template>
<style lang="scss" scoped></style>

即时搜索&防抖优化【后面再写】

即使搜索,实时请求。

路由缓存

<router-view v-slot="{ Component }">
      <keep-alive>
        <component :is="Component" />
      </keep-alive>
</router-view>

Comment

<script setup>
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
const route = useRoute()
const router = useRouter()
const like = ref(0)
const onClickLeft = () => {
  router.back()
}
const likeIcon = ref('good-job-o')
const onGoodClick = () => {
  console.log('点赞')
  like.value++
  likeIcon.value = 'good-job'

}
</script>

<template>
  <van-nav-bar title="歌曲评论" left-text="返回" left-arrow @click-left="onClickLeft" />
  <h1>评论页面</h1>
  <van-cell class="comment-item" title="name" label="2022-01-01 12:00:00">
    <!-- 将图片放置在单元格左侧 -->
    <template #icon>
      <van-image class="avatar" round width="3rem" height="3rem"
        src="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" />
    </template>
    <!-- 右侧图标 -->
    <template #right-icon>
      <span>{{ like }} &nbsp;</span><van-icon :name="likeIcon" size="1.5rem" class="icon" @click="onGoodClick" />
    </template>
    <h5 style="color: #333; float: left; text-align: left; width: 100%;">我的评价是一般,唱的太烂了</h5>
  </van-cell>
</template>

<style lang="scss" scoped>

.comment-item {
  display: flex;
  align-items: center;
  /* 确保所有内容垂直居中对齐 */
}

.avatar {
  margin-right: 1rem;
  /* 图片与文本之间的间隔 */
}

.icon {
  margin-left: auto;
  /* 自动填充剩余空间,将图标推到最右边 */
}
</style>

布局须知

1.使用2端固定,中间自适应时,info的flex:1时要注意,父容器要设置宽度。
2.组件库改样式,多使用插槽

下拉刷新

PullRefresh 下拉刷新 - Vant 4 (vant-ui.github.io)

	<van-pull-refresh v-model="loading" @refresh="onRefresh">
  </van-pull-refresh>

解决下拉刷新不生效的bug

扩展:上拉加载更多

  • 23
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值