上手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 版权协议,转载请附上原文出处链接和本声明。