vue3.0 RC版本出来的第一个练手项目

  • Post author:
  • Post category:vue




上手Vue3.0 ,用Vue-cli穿件项目4.5.4版本,可以直接搭建Vue3.0的

有个小活做个播放器,刚好可以花1天时间随便练手就选择了Vue3.0 ,

路由

import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    name: 'Home',
      component: () => import(/* webpackChunkName: "about" */ '../views/Home.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

主要代码,代码有些冗余,因为就一个页面所以也不考虑其他的

<template>
  <div class="home">
     <header class="header">
       <div class="header_left">
         <img :src="objData.coverurl" alt="">
       </div>
       <div class="header_right">
           <h5>歌单:{{objData.name}}</h5>
           <p>{{objData.description}}</p>
       </div>
     </header>
    <div style="padding: 10px;box-sizing: border-box">
      音乐列表 <span style="color: blue;font-size: 14px;font-weight: 600">{{recordtotal}}首)</span>
    </div>
    <div class="ul_list">
      <ul class="home_ul">
        <li class="home_li" style="border-top: 1px solid #ccc">
          <div class="left">编号</div>
          <div class="right">歌曲名称</div>
        </li>
        <li class="home_li" v-for="(item,index) in songList" :key="index" @click="playMuics(item,index)">
          <div class="left">{{index+1}}</div>
          <div class="right">
            {{item.id}}
          </div>
        </li>
        <li style="text-align: center;line-height: 40px;color: #ccc;font-size: 14px">{{msg}}</li>
      </ul>
    </div>

    <footer class="footer">
      <div class="bnt">
        <div @click="pre">
          <img src="../assets/images/aa3.png" alt="">
        </div>
        <div  @click="bf" v-if="!!isPlay">
          <img src="../assets/images/aa.png" alt="">
        </div>
        <div  @click="stop" v-else>
          <img src="../assets/images/aa1.png" alt="">
        </div>
        <div @click="nextbo">
          <img src="../assets/images/aa2.png" alt="">
        </div>
      </div>
      <div class="right">
        <audio id='music' :src="playObj.url">
        </audio>
        <p>
          {{playObj.id}}
        </p>
        <div class="press_box">
          <div class="press" @click="positionS($event)">
            <div class="press_width" :style="'width:'+widthLength"></div>
          </div>
          <div class="time">{{date(currentTime)}} / {{date(duration)}}</div>
        </div>
      </div>

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

<script>
// @ is an alias to /src
import {
    ref,
    onMounted,
    reactive,
    toRefs,
    getCurrentInstance,// 获取路由信息
} from 'vue'
import axios from 'axios'
import qs from 'qs'
let temp = null;
export default {
  name: 'Home',
  components: {
  },
  setup(){
      const src = ref('');
      const http = ref('http://***************');
      const  state = reactive({
          songIndex:0,//当前是第几首歌
          isPlay:true,//是否播放
          recordtotal:0,
          songList:[],//歌曲列表
          objData:{},//头部信息
          playObj:{
              id:'null'
          },//当前歌曲信息
          widthLength:'0%',//进度条
          currentTime:0,// 播放时间
          duration:0, // 歌单总时长
          currentTimeMiao:0,
          durationTimeMiao:0,
          msg:'这是我的底线',
          obj: {
              pageNo: 1,
              pageSize: 20,
              sysroleid: 1,
              userid: 0,
              songlistid:'' ,
          }
      })
      const list = ref([]);
      const {ctx} = getCurrentInstance();
       onMounted(()=>{
           state.obj.songlistid =ctx.$router.currentRoute.value.query&&ctx.$router.currentRoute.value.query.id?ctx.$router.currentRoute.value.query.id:'';
           axios.post(http.value+'/api/songlist/list',qs.stringify({
               pageNo: 1,
               pageSize: 1000,
               sysroleid: 1,
               userid: 0,
           }),{headers:{ 'Content-Type': 'application/x-www-form-urlencoded'}}).then(res1=>{
                 res1.data.data.forEach((item)=>{
                    if(item.id===+state.obj.songlistid){
                        state.objData = item;
                    }
                 });
           });
           axios.post(http.value+'/api/songlist/song',qs.stringify(state.obj),{headers:{ 'Content-Type': 'application/x-www-form-urlencoded'}}).then(res=>{
               state.songList = [...state.songList,...res.data.data];
               state.obj.pageNo++
               if(res.data.data.length>=20){
                   state.msg = '下拉加载更多'
               }else{
                   state.msg = '这是我的底线'
               }
               state.recordtotal = res.data.recordtotal;
               src.value = res.data.data[0].url;
               state.playObj = res.data.data[0];
               state.songIndex = 0;
//                   setTimeout(()=>{
//                       bf();
//                   },500)
           });
           document.querySelector('.home_ul').addEventListener('scroll',(e)=>{
               if((e.target.scrollHeight-1)<(e.target.clientHeight+e.target.scrollTop)){
                   axios.post(http.value+'/api/songlist/song',qs.stringify(state.obj),{headers:{ 'Content-Type': 'application/x-www-form-urlencoded'}}).then(res=>{
                       state.obj.pageNo++
                       if(res.data.data&&res.data.data.length>=20){
                           state.msg = '下拉加载更多'
                       }else{
                           state.msg = '这是我的底线'
                       }
                       if(!!res.data.data){
                           state.songList = [...state.songList,...res.data.data];
                       }

                   })
               }
           })
       });
      const date=(val)=>{
             if(isNaN(val)) return '00:00';
              let minutes = checkTime(parseInt(val*1000 / 1000 / 60 % 60, 10));//计算剩余的分钟
              let seconds = checkTime(parseInt(val*1000 / 1000 % 60, 10));//计算剩余的秒数
              function checkTime(i){ //0-9的数字前面加上0,例1变为01
                  if(i<10)
                  {
                      i = "0" + i;
                  }
                  return i;
              }
              return minutes+':'+seconds

      };
      const positionS=(e)=>{
          if(!state.isPlay){
              let  bofang = document.getElementById('music');
              bofang.currentTime =(e.offsetX/e.target.clientWidth)*bofang.duration;
          }

      };
      function getMuisc(bofang) {
          setTimeout(()=>{
              bofang.play();
          },1);
          temp = setInterval(()=>{
              state.currentTime = bofang.currentTime;
              state.duration = bofang.duration;
              state.widthLength = bofang.currentTime/bofang.duration>=1?'100%':(bofang.currentTime/bofang.duration*100)+'%';
              if(state.widthLength=='100%'){
                  state.songIndex++;
                  if(state.songIndex>state.songList.length-1){
                      state.songIndex = 0
                  }
                  state.playObj = state.songList[state.songIndex];
                  setTimeout(()=>{
                      bofang.play();
                  },1)

              }
          },30)
      }
      const bf=()=>{
          //播放  duration//播放时长 currentTime//当前播放时间
          state.isPlay = false;
          let  bofang = document.getElementById('music');
          getMuisc(bofang);
      }
      const stop=()=>{
          //暂停
          state.isPlay = true;
          let  bofang = document.getElementById('music');
              bofang.pause();
              clearInterval(temp);
      }
      const playMuics=(opction,i)=>{
          state.isPlay = true;
//          state.playObj = opction;
          state.songIndex = i;
          state.playObj = state.songList[state.songIndex];
          bf()
      }
      const pre=()=>{
         //上一曲
          state.songIndex--;
          state.isPlay = true;
          state.currentTime= 0;
          if(state.songIndex<0){
              state.songIndex = state.songList.length-1
          }
          state.playObj = state.songList[state.songIndex];
          setTimeout(()=>{
              bf();
          },1)
      }
      const nextbo=()=>{
          //下一曲
          state.songIndex++;
          state.isPlay = true;
          if(state.songIndex>state.songList.length-1){
              state.songIndex = 0
          }
          state.playObj = state.songList[state.songIndex];
          setTimeout(()=>{
              bf();
          },1)
       }
      return {
          src,http,list,...toRefs(state),bf,playMuics,pre,nextbo,stop,date,positionS
      }
  }
}
</script>
<style scoped lang="less">
  .home{
    width: 100%;
    max-width: 1024px;
    min-width: 320px;
    height: 100%;
    position: relative;
  }
  .header{
    width: 100%;
    height: 100px;
    padding: 10px;
    box-sizing: border-box;
    display: flex;
    flex-wrap: wrap;
    .header_left{
      width: 80px;
      height: 80px;
      img{
        display: block;
        width: 80px;
        height: 80px;
      }
    }
    .header_right{
      flex: 1;
      padding: 10px 5px;
      box-sizing: border-box;
      overflow: hidden;
      h5{
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        word-break: break-all;
        font-size: 16px;
        font-weight: 600;
      }
      p{
        font-size: 13px;
        margin-top: 2px;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        word-break: break-all;
        overflow: hidden;
      }
    }
  }
  .ul_list{
    position: absolute;
    left: 0;
    right: 0;
    top: 141px;
    bottom: 80px;
    overflow: hidden;
  }
  .home_ul{
    position: absolute;
    left: 0;
    right: -16px;
    top:0;
    bottom: 10px;
    padding:0 26px 0 10px;
    overflow-y: auto;
    .home_li{
      width: 100%;
      height: 40px;
      line-height: 40px;
      text-align: center;
      display: flex;
      border: 1px solid #ccc;
      border-top: 0;
      font-size: 13px;
      .left{
        flex: 1;
        border-right: 1px solid #ccc;
      }
      .right{
        width: 100%;
        flex: 4;
        text-align: left;
        padding: 0 5px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        word-break: break-all
      }
    }
    .home_li:nth-child(2n){
      background: #fff;
    }
  }

  .footer{
    width: 100%;
    height: 80px;
    position: absolute;
    left: 0;
    bottom: 0;
    background: #2e2d2e;
    display: flex;
    flex-wrap: wrap;
    padding: 10px;
    box-sizing: border-box;
    >.bnt{
      width: 30%;
      overflow: hidden;
      >div{
        width: 30%;
        height: 60px;
        float: left;
        display: flex;
        justify-content: center;
        align-items: center;
        img{
          display: block;
          width: 20px;
          height: 20px;
        }
      }
      >div:nth-child(2){
        width: 40%;
        img{
          width: 30px;
          height: 30px;
        }
      }
      >div:nth-child(1){
        justify-content: flex-end;
      }
      >div:nth-child(3){
        justify-content: flex-start;
      }
    }
    .right{
      width: 70%;
      height: 60px;
      padding: 8px 0 0 0;
      box-sizing: border-box;
      >p{
        width: 100%;
        margin-bottom: 5px;
        color: #fff;
      }
      >.press_box{
        width: 100%;
        display: flex;
        flex-wrap: wrap;
        >.press{
          width: 63%;
          height: 8px;
          background: #f1f1f1;
          .press_width{
            height: 100%;
            width: 0;
            background: #f76971;
          }
        }
        >.time{
          width: 37%;
          text-align: right;
          color: #fff;
          font-size: 12px;
          text-align: right;
          transform: translateY(-4px);
        }
      }
    }

  }

</style>

效果
在这里插入图片描述

播放效果实现了快进,倒退,暂停,上下一首,点击列表播放,

vue3.0本地跑的没有问题,但是一上线提示‘currentRoute’为undfind,我是为了去url上的参数所以用了Vue3.0的

const {ctx} = getCurrentInstance();ctx.$router.currentRoute.value.query去取值,网上也没找到合适的,所以我用回了字符串截取的方法重新上线了。



版权声明:本文为m18565890306原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。