WEB音乐播放器
闲来无事,利用VUE搭建了一个WEB音乐播放器。但由于前期没有构思好,导致项目进行不下去了。不过实现了最基本的功能。记录一下项目过程吧。最终效果图如下:项目搭建采用vue-cli3.0搭建脚手架。采用babel+eslint配置。项目结构图(node_modules未显示)项目说明播放器中定义了三个组件,App.vue(父组件),Content.vue,Controller...
·
闲来无事,利用VUE搭建了一个WEB音乐播放器。但由于前期没有构思好,导致项目进行不下去了。不过实现了最基本的功能。记录一下项目过程吧。
最终效果图如下:
项目搭建
- 采用vue-cli3.0搭建脚手架。
- 采用babel+eslint配置。
- 项目结构图(node_modules未显示)
项目说明
- 播放器中定义了三个组件,App.vue(父组件),Content.vue,Controller.vue。
- 未采用npm安装的方式,而是采用直接引入js和css的方式。
- 引入了vue-resource进行网络请求。
- API来源于小伟博客。
代码
一、App组件
<template>
<div id="app">
<div class="search-box">
<input class="form-control" type="text" placeholder="搜索音乐,歌手,歌词,mv" v-model="keywords">
<button class="btn btn-primary" @click="search">SOU一下</button>
</div><br>
<button class="btn btn-default" data-toggle="modal" data-target="#myModal">
<span class="glyphicon glyphicon-camera"></span>定制皮肤
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">定制个性皮肤</h4>
</div>
<div class="modal-body">
<input type="text" name="" id="" placeholder="请在此处粘贴您的背景图片地址" class="form-control" v-model="imglink">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" @click="changeImage">保存</button>
</div>
</div>
</div>
</div>
<Content :musics='musics' @playStatus="getPlayStatus"></Content>
<Control :playStatus="playStatus"></Control>
</div>
</template>
<script>
import Content from './components/Content.vue'
import Control from './components/Control.vue'
export default {
data() {
return {
keywords: '',
musics: {},
imglink: '',
playStatus: {}
}
},
components:{
Content,
Control
},
created: function(){
this.$http.get('https://api.mlwei.com/music/api/?key=523077333&id=热门&type=so&cache=0&size=hq&nu=10')
.then( (res)=>{
this.musics = res.body.Body;
})
},
methods:{
search: function(){
this.$http.get('https://api.mlwei.com/music/api/?key=523077333&id='+ this.keywords +'&type=so&cache=0&size=hq&nu=10')
.then( (res)=>{
this.musics = res.body.Body;
})
},
changeImage: function(){
$('#app').css({'background-image':'url('+this.imglink+')'});
},
getPlayStatus: function(playStatus){
this.playStatus = playStatus;
}
}
}
</script>
<style scoped>
#app{
height: 100%;
width: 100%;
}
.search-box{
margin-left: 35%;
margin-top: 4%;
}
.search-box input{
display: inline;
width: 30%;
}
button[class='btn btn-default']{
float: right;
margin-right: 160px;
margin-top: 5px;
}
</style>
二、Content组件
<template>
<div id="content">
<ul class="nav nav-tabs bg-info" role="tablist">
<li role="presentation"><a href="#">音乐</a></li>
<li role="presentation"><a href="#">歌手</a></li>
<li role="presentation"><a href="#">歌词</a></li>
<li role="presentation"><a href="#">MV</a></li>
</ul>
<hr>
<table>
<thead>
<td>操作</td>
<td>歌曲名称</td>
<td>歌手</td>
<td>专辑</td>
</thead>
<tr v-for="(music,index) in musics" :key="music.mid">
<td><a @click="play(index)"><span class="glyphicon glyphicon-play-circle"></span></a></td>
<td>{{ music.title }}</td>
<td>{{ music.author }}</td>
<td>{{ music.album }}</td>
<audio controls id="audio">
<source :src="music.url" type="audio/mpeg">
</audio>
</tr>
</table>
</div>
</template>
<script>
export default {
props:['musics'],
data(){
return{
playStatus : {'isPlay':false,'currentTime':0}
}
},
methods:{
play: function(index){
var audio = document.getElementsByTagName('audio')[index];
if(audio.paused){
audio.load();
audio.play();
this.playStatus.isPlay = true;
this.playStatus.currentTime = audio.currentTime;
this.$emit('playStatus',this.playStatus);
}else{
audio.pause();
this.playStatus.isPlay = false;
this.$emit('playStatus',this.playStatus);
}
}
}
}
</script>
<style scoped>
ul{
width: 80%;
margin-left: 10%;
}
table{
width: 80%;
margin-left: 10%;
line-height: 30px;
}
table>tr>td{
border-bottom: 1px solid rgb(79.8%, 96%, 79.8%);
}
button{
margin: 0;
padding: 0;
border: 1px solid transparent;
outline: none;
background-color:rgb(100%, 100%, 100%);
}
audio{
display: none;
}
</style>
三、Control组件
<template>
<div id="control">
<button class="btn btn-primary">
<span class="glyphicon glyphicon-fast-backward"></span>
</button>
<button class="btn btn-primary" @click="play">
<span :class="playStatus.isPlay ? 'glyphicon glyphicon-pause' : 'glyphicon glyphicon-play'"></span>
</button>
<button class="btn btn-primary">
<span class="glyphicon glyphicon-fast-forward"></span>
</button>
<div class="progress" >
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100">
<span class="sr-only">60% Complete</span>
</div>
</div>
<div id="other">
<button>词</button>
<button>
<span class="glyphicon glyphicon-repeat"></span>
</button>
<button>
<span class="glyphicon glyphicon-film"></span>
</button>
<button>
本
</button>
</div>
</div>
</template>
<script>
export default {
props: ['playStatus'],
data(){
return{
playcss: 'glyphicon glyphicon-play',
}
},
methods:{
play:function(){
}
}
}
</script>
<style scoped>
#control{
width: 80%;
padding-left: 10%;
padding-top: 3%;
}
button{
height: 40px;
width: 40px;
border-radius: 50%;
margin-right: 20px;
}
#progress{
width: 60%;
height: 3px;
}
div[class='progress']{
height: 3px;
width: 30%;
position: absolute;
left: 24%;
top: 87%;
}
div[class='progress-bar']{
width: 60%;
height: 3px;
}
#other{
position: absolute;
left: 75%;
top: 84%;
}
</style>
四、main.js
import Vue from 'vue'
import App from './App.vue'
import VueResource from 'vue-resource'
Vue.config.productionTip = false
Vue.use(VueResource)
new Vue({
render: h => h(App),
}).$mount('#app')
项目功能展示
- 定制皮肤
采用bootstrap中的模态框对图片地址进行获取,并采用jQuery进行背景的渲染。
- 音乐搜索
父组件调用API获取歌曲数据,将数据与Content组件进行绑定。Content利用props对数据进行获取并对页面进行渲染。
- 音乐播放
点击音乐所对应的播放键,生成歌曲状态信息(歌曲是否播放,歌曲播放进度),将歌曲信息先传递给父组件,再由父组件传递给Control组件,从而实现联动。
问题就出在这里,由于vue的特性是子组件和子组件之间不能进行传值,因此,只能采取这种迂回的方法。
项目总结
这个播放器的项目由于前期构思的问题,导致组件间传值变得很困难。因此,vue的项目在组件构思上一定要考虑组件间传值的问题。
项目中还遇到一个问题,在利用vue-resource进行请求的过程中,可能会出现无法请求的问题,这个时候一定要先对请求URL进行判断,其次,要注意请求的方式,小编在调用一个API时,调用成功,却始终无法取到返回值,就是在请求方式上出现了问题,最开始小编使用的是this.$http.get() 方法进行请求,最后采用this.$http.jsonp()成功请求并取到值。
更多推荐
已为社区贡献1条内容
所有评论(0)