其他页面实现可以看我的主页,如果对你有帮助请点一个赞或收藏
整体效果
1、首先是路由跳转的主页面 ListView.vue
<template>
<div class="listView">
<!-- 传递参数给子组件 -->
<listviewtop :playlist = "state.playlist"></listviewtop>
<listviewIcon :playlist = "state.playlist"></listviewIcon>
<playlistView :playlist = "state.playlist"></playlistView>
</div>
</template>
<script>
import listviewtop from '@/components/listView/listviewTop.vue'
import listviewIcon from '@/components/listView/listviewIcon.vue'
import playlistView from '@/components/listView/palylistView.vue'
import {postPlaylistDetail} from '@/api/index';
import { onMounted ,reactive} from 'vue';
import {useRoute} from 'vue-router'
export default {
components:{
listviewtop,
listviewIcon,
playlistView
},
setup(){
const route = useRoute()
let state = reactive ({
list:[],
playlist:{
creator:{},
tracks:{}
},
})
onMounted(async()=>{
// 获取传入的id
let id = route.query.id
let result = await postPlaylistDetail(id)
state.playlist = result.data.playlist
})
return{
state
}
}
}
</script>
<style lang="less" scoped>
.listView{
width: 7.5rem;
}
</style>
2、listviewTop.vue顶部
然后是三个子组件,listviewTop.vue顶部
<template>
<div class="listViewTop">
<img class="bg" :src="playlist.coverImgUrl" alt="">
<div class="listViewTopNav">
<div class="left">
<!-- 返回按钮 -->
<div class="back" @click="$router.back()">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xitongfanhui"></use>
</svg>
</div>
<!-- 歌单 -->
<div class="title">
歌单
</div>
</div>
<!-- 搜索按钮 和 更多按钮-->
<div class="right">
<div class="search">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-sousuo"></use>
</svg>
</div>
<div class="more">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-gengduo-shuxiang"></use>
</svg>
</div>
</div>
</div>
<!-- 头像 简介部分 -->
<div class="content">
<div class="content_left">
<!-- 头像 -->
<div class="hp">
<img class="headPortrait" :src="playlist.coverImgUrl" alt="">
<div class="count">
<span>▷</span>
<!--播放量 -->
<span>{{formatNum(playlist.playCount)}}</span>
</div>
</div>
<!-- 头像下面的小方块 -->
<div class="headPortraitBlock">
<img class="headPortraitBlockBG" :src="playlist.coverImgUrl" alt="">
</div>
</div>
<div class="contnet_right">
<div class="rightTop">
<!-- 歌单用户姓名 -->
<div class="UserTitle">
<p>{{playlist.name}}</p>
</div>
<!-- 更多图标 -->
<div class="contnet_right_more">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-gengduo"></use>
</svg>
</div>
</div>
<!-- 用户头像和姓名 -->
<div class="UserInfo">
<!-- 头像 -->
<div class="UserImg">
<img class="UserPortrait" :src="playlist.creator.avatarUrl">
</div>
<!-- 名称 -->
<div class="UserName">
<p>{{playlist.creator.nickname}}</p>
</div>
<!-- 关注图标 -->
<div class="UserAttention">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-plus"></use>
</svg>
</div>
</div>
<!-- 用户简介 -->
<div class="UserAbout">
<div class="description">
<p>{{playlist.description}}</p>
</div>
<div class="UserAboutMore">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-gengduo1"></use>
</svg>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { computed } from 'vue'
export default {
props:['playlist'],
setup(){
// 格式化输出听歌人数
const formatNum = computed(()=>{
return function(num){
if(num>10000) return (num/10000).toFixed(2) + '万'
}
})
return {
formatNum
}
}
}
</script>
<style lang="less" scoped>
.listViewTop{
width: 7.5rem;
padding: 0 0.4rem;
// border: 1px solid red;
// height: 5rem;
border-radius: 0 0 10% 10%;
overflow: hidden;
.bg{
position:fixed;
left:0;
top: 0;
width: 7.5rem;
// height: auto;
z-index: -1;
// 设置滤镜模糊
filter: blur(150px);
overflow: hidden;
height: 4rem;
transform: scale(4);
}
.listViewTopNav{
display: flex;
justify-content: space-between;
align-items: center;
height: 1.2rem;
font-size: 0.35rem;
.icon{
width: 0.5rem;
height: 0.5rem;
fill: #fff;
}
.title{
margin-left: 0.4rem;
}
.search{
margin-right: 0.5rem;
}
}
.left,.right{
display: flex;
color: #fff;
}
// 标题 头像部分
.content{
display: flex;
justify-content: space-between;
margin-top: 10px;
}
// 左边头像部分
.content_left{
position: relative;
// 头像
.hp{
position: absolute;
z-index: 2;
top: 8px;
}
.headPortrait{
width: 2.5rem;
height: 2.5rem;
border-radius: 10%;
}
.headPortraitBlock{
position: absolute;
z-index: 1;
left: 13px;
// 隐藏超出的部分
overflow: hidden;
border-radius: 10px;
.headPortraitBlockBG{
width: 2rem;
height: 2rem;
background-size: cover;
filter: blur(50px);
// 局部放大取颜色
transform: scale(3);
}
}
.count{
position: absolute;
right: 0.1rem;
top: 0.1rem;
font-size: 0.24rem;
color:rgb(246,247,250);
border-radius:10px;
background-color: rgba(19, 19, 19, 0.2);
}
}
// 右边歌单名和用户简介部分
.contnet_right{
width: 4rem;
height: 2.5rem;
.rightTop{
display: flex;
justify-content: space-around;
height: 1.25rem;
.UserTitle{
color: #fff;
font-size: 15px;
}
.icon{
fill: #fff;
width: 0.5rem;
height: 0.5rem;
}
}
// 用户信息
.UserInfo{
display: flex;
color: rgba(255, 255, 255, 0.5);
.UserPortrait{
width: 0.5rem;
height: 0.5rem;
border-radius: 100%;
}
.UserName{
height: 26px;
padding-left: 4px;
font-size: 10px;
line-height: 26px;
}
.UserAttention{
width: 0.7rem;
height: 0.5rem;
background-color: rgba(207, 207, 207, 0.5);
margin-left: 10px;
border-radius: 12px;
display: flex;
.icon{
align-self: center;
margin:0 auto;
fill: rgba(255, 255, 255, 0.6);
}
}
}
// 用户简介
.UserAbout{
display: flex;
justify-content: space-around;
margin-top: 0.3rem;
width: 3.5rem;
color: rgba(255, 255, 255, 0.5);
.description{
width: 3rem;
font-size: 14px;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
}
.icon{
align-self: center;
margin:0 auto;
fill: rgba(255, 255, 255, 0.6);
}
}
}
}
</style>
3、listviewIcon.vue
然后就是导航栏的子组件部分 listviewIcon.vue
<template>
<div class="listviewIcon">
<!-- 收藏 -->
<div class="collectIcon">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-shoucangjia"></use>
</svg>
<p>{{playlist.subscribedCount}}</p>
</div>
<!-- 评论 -->
<div class="commentIcon">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-pinglun-"></use>
</svg>
<p>{{playlist.commentCount}}</p>
</div>
<!-- 分享 -->
<div class="shareIcon">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-fenxiang"></use>
</svg>
<p>{{playlist.shareCount}}</p>
</div>
</div>
</template>
<script>
export default {
props:['playlist'],
}
</script>
<style lang="less" scoped>
.listviewIcon{
width: 6rem;
display: flex;
justify-content: space-around;
// border: 1px solid red;
border-radius: 20px;
padding: 10px;
// margin: 0.7rem auto -25px auto;
background: #fff;
// 阴影
box-shadow: 0px 1px 10px -4px rgba(0, 0, 0, 0.2);
font-size: 13px;
// 让它在播放列表的上面
position: absolute;
z-index: 1;
left: 0.7rem;
top: 4.5rem;
.icon{
width: 0.5rem;
height: 0.5rem;
margin-right: 10px;
}
}
.listviewIcon div:nth-child(n){
display: flex;
justify-content: center;
align-items: center;
}
.listviewIcon div:nth-child(n + 2) { //n+2就是从第二个元素开始往后所有的元素
border-left: 1px solid rgba(77, 77, 77, 0.5);
padding-left: 20px;
}
</style>
4、playlistView.vue
然后就是播放列表的子组件,playlistView.vue
<template>
<div class="playlistView">
<!-- 图标栏 -->
<div class="playlistIcon">
<div class="leftIcon">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-bofang"></use>
</svg>
<p class="words">播放全部</p>
<p class="count">({{playlist.tracks.length}})</p>
</div>
<div class="rightIcon">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-xiazai"></use>
</svg>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-quanxuan"></use>
</svg>
</div>
</div>
<!-- 播放列表栏 -->
<div class="playlists">
<div class="playItem" v-for="(item,i) in playlist.tracks" :key="i">
<!-- 列表左边区域 -->
<div class="left">
<!-- 编号 -->
<div class="index">{{i+1}}</div>
<div class="content">
<!-- 音乐名 -->
<div class="title">{{item.name}}</div>
<!-- 作者名和专辑名 -->
<div class="anthor">{{item.ar[0].name}} - {{item.al.name}}</div>
</div>
</div>
<!-- 列表右边区域 -->
<div class="right">
<!-- 图标部分 -->
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-bofang"></use>
</svg>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-gengduo-shuxiang"></use>
</svg>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props:['playlist'],
setup(){
}
}
</script>
<style lang="less" scoped>
.playlistView{
width: 7.5rem;
background-color: rgb(255, 255, 255);
margin-top:1rem;
padding: 1rem 0.4rem 0 0.4rem;
.icon{
width: 0.5rem;
height: 0.5rem;
}
.words{
margin-right: 5px;
line-height: 0.5rem;
}
.count{
font-size: 10px;
line-height: 0.5rem;
}
}
.playlistIcon{
display: flex;
justify-content: space-between;
align-items: center;
}
.playlistIcon div:nth-child(n){
display: flex;
justify-content: space-between;
align-items: center;
}
.rightIcon svg:nth-child(1){
margin-right: 15px;
}
.leftIcon svg:nth-child(1){
margin-right: 15px;
fill: red;
}
// 播放列表栏
.playlists{
margin-top: 0.5rem;
.playItem{
display: flex;
justify-content: space-between;
margin-top: 0.5rem;
.left{
display: flex;
justify-content: space-between;
// align-items: center;
// 编号
.index{
width: 0.5rem;
font-size: 20px;
opacity: 0.5;
display: flex;
justify-content:center;
align-items:center;
}
// 作者名和专辑名
.content{
margin-left: 0.4rem;
.anthor{
font-size: 10px;
opacity: 0.5;
}
}
}
.right{
.icon{
width: 0.5rem;
height: 0.5rem;
opacity: 0.5;
margin-left: 15px;
}
}
}
}
</style>
整体效果