Vue3+node.js网易云音乐实战项目(四)

一、图标列表界面

image-20220614170858639

首先,我们看一下接口文档,看需要请求什么接口

image-20220616120841192

然后我们在components下新建一个子组件

image-20220616121040695

首先,先引用一下axios,请求一下接口看看是不是我们需要的图片

<script>
import axios from 'axios'
import {reactive} from 'vue'
export default {
    setup(){
      let images = reactive({
        list:[]
      })
        axios.post(`http://localhost:3000/homepage/dragon/ball`).then((res)=>{
            images.list = res.data.data
        });
        console.log(images);
        return {
          images
        }
    }
}
</script>

image-20220616121222477

我们可以看到这些就是我们需要的图片,然后我们考虑渲染到页面上

首先,我们利用v-for循环,可以看到整个部分分为上面图片部分,和下面文字页面

<template>
  <div class="swipe">
    <span v-for="(ima,index) in images.list" :key="index">
      <img :src="ima.iconUrl"/>
        <p>{{ima.name}}</p>
    </span>
  </div>
</template>

效果大概就是这个样子

image-20220616151750474

然后我们首先考虑就是把它变为横排列并且可以滑动,利用 flex 和 overflow-y

 .swipe {
        display: flex;
        overflow-y: auto;
     	text-align: center;
 }

效果

3546424423

然后我们需要取消下面的滑动条,利用伪对象选择器

 .swipe::-webkit-scrollbar {
        display: none;
  }

35464224423

效果已经很接近了,然后我们稍微调一下图片背景颜色,并变成圆形

  img{
    width: 1rem;
    height: 1rem;
    border-radius: 100%;
    background: rgb(254,90,89);
  }

image-20220616152534962

可以看出来很紧凑,我们调一下边距 和字体大小

  .swipe span {
      margin: 18px 0px 0px 18px;
  }
  .swipe p {
      font-size: 0.1rem;
      align-items: center;
      opacity: 0.7;
  }

效果就出来了

image-20220616152726007

然后我们挪一下请求代码,同样在api文件夹里面的index.js下

//圆形图标入口列表
function postIcon(){
   return axios.post(`http://localhost:3000/homepage/dragon/ball`).then((res)=>{
        return res.data.data
    });
}

image-20220616152900116

修改一下iconList.vue里的代码

<script>
import {postIcon} from '@/api/index'
import {reactive,onMounted} from 'vue'
export default {
    setup(){
      let images = reactive({
        list:[]
      })

      onMounted(()=>{
        getSwipeAPI()
      })

      // 获取入口图片
      async function getSwipeAPI(){
          images.list = await postIcon()
      }

      return {
          images
      }
    }
}
</script>

完整代码

<template>
  <div class="swipe">
    <span v-for="(ima,index) in images.list" :key="index">
      <img :src="ima.iconUrl"/>
        <p>{{ima.name}}</p>
    </span>
  </div>
</template>

<script>
import {postIcon} from '@/api/index'
import {reactive,onMounted} from 'vue'
export default {
    setup(){
      let images = reactive({
        list:[]
      })

      onMounted(()=>{
        getSwipeAPI()
      })

      // 获取入口图片
      async function getSwipeAPI(){
          images.list = await postIcon()
      }

      return {
          images
      }
    }
}
</script>

<style lang="less" scoped>
  img{
    width: 1rem;
    height: 1rem;
    border-radius: 100%;
    background: rgb(254,90,89);
  }
  .swipe {
        display: flex;
        overflow-y: auto;
        text-align: center;
  }

 .swipe::-webkit-scrollbar {
        display: none;
  }

  .swipe span {
     margin: 18px 0px 0px 18px;
  }
  .swipe p {
      font-size: 0.1rem;
      align-items: center;
      opacity: 0.7;
  }

</style>

二、推荐歌单界面

接下来,我们实现推荐歌单部分

image-20220616163635856

我们可以看到推荐歌单主要由上面的导航栏部分和下面的图片部分组成

我们首先实现上面部分,在components中创建一个recommendMusic.vue的子组件

image-20220616163759646

里面填上基本的结构

<template>
    <!-- 每日推荐和推荐歌单中间的线条 -->
    <van-divider />
  <div class="musicList">
      <!-- 顶部推荐歌单 -->
      <div class="musicList-top">
          <div class="title">推荐歌单</div>
          <div class="more">
              更多<van-icon name="arrow" />
           </div>
      </div>
        <!-- 歌单部分 -->
      <div class="songList">

      </div>
  </div>
</template>

注意 和 是vant里面的分割线和图标,我忘记找返回图标了,所以就用了vant里面的

image-20220616164056547

分割线有点不明显,大概效果就是这样,然后我们来调整样式,利用flex调整

.musicList-top{
    display: flex;
    justify-content: space-between;
    margin: 5px 15px 10px 15px;
}

image-20220616164242321

在调整 更多 的样式,把他字体变小然后给它加一个边框,再调整颜色

      .more{
        width: 50px;
        height: 20px;
        font-size: 10px;
        border: 1px solid rgb(224, 224, 224);
        border-radius: 10px;
        text-align: center;
        padding-left: 5px;
    }

image-20220616164414603

然后在调整左边的 推荐歌单,字体给它变粗一点

    .title{
        font-weight: 900;
    }

image-20220616164455507


然后我们来实现下面的部分

image-20220616164619027

这个很像我们做的每日推荐的样式,我们还是来看一下接口数据,同样利用axios请求一下接口

image-20220616164840645

<script>
import axios from 'axios'
export default {
    setup(){
        axios.post(`http://localhost:3000/recommend/resource`).then((res)=>{
            console.log(res);
        });
    }
}
</script>

image-20220616164911357

然后我们把请求的数据返回给页面

<script>
import axios from 'axios'
import {onMounted,reactive} from 'vue'
export default {
    setup(){
        let songlistResult = reactive({
            list:[]
        })
        axios.post(`http://localhost:3000/recommend/resource`).then((res)=>{
            songlistResult.list = res.data.recommend
        })
        return {songlistResult}
    }
}
</script>

既然我们的需要的效果和每日推荐的效果差不多,我们就先复制上面的样式

 <!-- 歌单部分 -->
      <div class="songList">
        <div class="imgs" v-for="(img,index) in songlistResult.list" :key="index" >
            <img :src="img.picUrl"/>
            <div class="count">{{img.playcount}}</div>
            <p>{{img.name}}</p>
         </div>
      </div>
// 歌单部分样式
  img{
    width: 1rem;
    height: 1rem;
    border-radius: 100%;
    background: rgb(254,90,89);
  }
  .songList {
        display: flex;
        overflow-y: auto;
        text-align: center;
  }

 .songList::-webkit-scrollbar {
        display: none;
  }

  .songList .imgs {
      margin: 18px 0px 0px 18px;
  }
  .songList p {
      font-size: 0.1rem;
      align-items: center;
      opacity: 0.7;
  }

354642242423

现在的效果就是上面这样,然后我们在来调整部分的样式

这里我调整了一下宽度和高度,然后把居中对齐取消,最后调整了一下边距

 // 只展示修改的部分
img{
    width: 2rem;
    height: 2rem;
    border-radius: 10%;
    background: rgb(254,90,89);
  }
  .songList {
        display: flex;
        overflow-y: auto;  
  }
  .songList .imgs {
      margin: 10px 0px 0px 10px;
  }

image-20220616171642725

接着我们把听音乐的人数调整一下,利用相对定位和绝对定位把人数固定在右上角

  .songList .imgs {
      margin: 10px 0px 0px 10px;
      position: relative;
  }
    .count{
        position: absolute;
        right: 0.1rem;
        top: 0.1rem;
        font-size: 0.24rem;
        color:rgb(246,247,250) ;
    }

image-20220616184708357

然后我们在稍微的调整一下,给他加个小三角形,这里我偷个懒直接用win10自带的输出法里面的三角形,在调整一下背景颜色

 <span></span>
 .count{
        position: absolute;
        right: 0.1rem;
        top: 0.1rem;
        font-size: 0.24rem;
        color:rgb(246,247,250);
        border-radius:10px;
         //a代表透明度
        background-color: rgba(19, 19, 19, 0.4);
    }

image-20220616200750496

然后我们在给他加个万,利用computed计算属性,去对数字进行格式化操作

        // 格式化输出听歌人数
        const formatNum = computed(()=>{
           return function(num){
                if(num>10000) return (num/10000).toFixed(2) + '万'
            }
        })

image-20220616200910261

然后我们在整理一下,请求接口,同样把请求丢在api/index.js里面

// 推荐歌单
function postRecommendMusic(){
   return axios.post(`http://localhost:3000/recommend/resource`).then((res)=>{
        return res.data.recommend
    })
}

image-20220616201011237

整理一下.vue的js代码

<script>
import {postRecommendMusic} from '@/api/index'
import {onMounted,reactive,computed} from 'vue'
export default {
    setup(){
        let songlistResult = reactive({
            list:[]
        })

        onMounted(()=>{
            getRecommendMusicAPI()
        })

        // 格式化输出听歌人数
        const formatNum = computed(()=>{
           return function(num){
                if(num>10000) return (num/10000).toFixed(2) + '万'
            }
        })
        // 请求数据
        async function getRecommendMusicAPI(){
          songlistResult.list = await postRecommendMusic()
        }

        return {songlistResult,formatNum}
    }
}
</script>

完整代码

<template>
    <!-- 每日推荐和推荐歌单中间的线条 -->
    <van-divider />
  <div class="musicList">
      <!-- 顶部推荐歌单 -->
      <div class="musicList-top">
          <div class="title">推荐歌单</div>
          <div class="more">
              更多<van-icon name="arrow" />
           </div>
      </div>
        <!-- 歌单部分 -->
      <div class="songList">
        <div class="imgs" v-for="(img,index) in songlistResult.list" :key="index" >
            <img :src="img.picUrl"/>
            <div class="count">
                <span>▷</span>
                <span>{{formatNum(img.playcount)}}</span>
            </div>
            <p>{{img.name}}</p>
         </div>
      </div>
  </div>
</template>

<script>
import {postRecommendMusic} from '@/api/index'
import {onMounted,reactive,computed} from 'vue'
export default {
    setup(){
        let songlistResult = reactive({
            list:[]
        })

        onMounted(()=>{
            getRecommendMusicAPI()
        })

        // 格式化输出听歌人数
        const formatNum = computed(()=>{
           return function(num){
                if(num>10000) return (num/10000).toFixed(2) + '万'
            }
        })
        // 请求数据
        async function getRecommendMusicAPI(){
          songlistResult.list = await postRecommendMusic()
        }

        return {songlistResult,formatNum}
    }
}
</script>

<style lang="less" scoped>
// 推荐歌单部分样式
    .musicList-top{
        display: flex;
        justify-content: space-between;
        margin: 5px 15px 10px 15px;
        .title{
            font-weight: 900;
        }
        .more{
            width: 50px;
            height: 20px;
            font-size: 10px;
            border: 1px solid rgb(224, 224, 224);
            border-radius: 10px;
            text-align: center;
            padding-left: 5px;
        }
    }
// 歌单部分样式
  .songList {
        display: flex;
        overflow-y: auto;  
  }
  img{
    width: 2rem;
    height: 2rem;
    border-radius: 10%;
    background: rgb(254,90,89);
    
  }



 .songList::-webkit-scrollbar {
        display: none;
  }

  .songList .imgs {
      margin: 10px 0px 0px 10px;
      position: relative;
  }
 .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.4);
    }
  .songList p {
      font-size: 0.1rem;
      align-items: center;
      opacity: 0.7;
  }


</style>

三、链接

Vue3+node.js网易云音乐实战项目(一): https://blog.csdn.net/NITIQ/article/details/125358363?spm=1001.2014.3001.5501
Vue3+node.js实战项目网易云音乐APP(二): https://blog.csdn.net/NITIQ/article/details/125358401?spm=1001.2014.3001.5502
Vue3+node.js网易云音乐实战项目(三): https://blog.csdn.net/NITIQ/article/details/125358446?spm=1001.2014.3001.5502
Vue3+node.js网易云音乐实战项目(四): https://blog.csdn.net/NITIQ/article/details/125358476?spm=1001.2014.3001.5502

未完…

未完…

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周粥粥ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值