在家闲着没事,学习了一下vue.js,不得不说vue.js用起来真的是太方便了.
如果早学会了vue.js,那大一大二的课设应该都是直接秒了hh.
学习之后用vue.js配合element-ui做了一个音乐播放器,当然用的是别人的接口.
vue.js基础知识
数据驱动是vuejs最大的特点。在vue.js中,所谓的数据驱动就是当数据发生变化的时候,用户界面发生相应的变化,开发者不需要手动的去修改dom。传统前端开发中需要频繁操作dom元素,当逻辑比较复杂时代码就会很复杂,效率太低了.而vue.js数据驱动,开发快,用element-ui很快就能做个应用,配合flask应该是开发效率最高的组合了.
vue.js实现数据驱动是通过mvvm框架来实现的,其中,数据(Model)和视图(View)是不能直接通讯的,而是需要通过ViewModel来实现双方的通讯。当数据变化的时候,viewModel能够监听到这种变化,并及时的通知view做出修改。同样的,当页面有事件触发时,viewMOdel也能够监听到事件,并通知model进行响应。Viewmodel就相当于一个观察者,监控着双方的动作,并及时通知对方进行相应的操作。
Vue.js的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统,vue.js中封装了很多方法.
v-if
: 用来控制dom元素是否显现.v-show
: 同样也是控制dom元素是否显现的方法,与v-if不同的是v-if是通过删除dom元素来实现效果,而v-show是通过注释掉dom元素来实现效果,性能上来说是v-show好一点.v-for
: for循环,常用场景是提取列表或者数组里面的值.v-on
: 也可以简写成@
,为dom元素绑定一个事件,可以是键盘点击事件或者鼠标点击事件.v-bind
:用来绑定数据和元素属性,绑定之后,就可以直接在dom元素里调用vue对象里声明的data了.可以简写成:
.v-model
: 用来将dom元素和data双向绑定,双向绑定的含义是其中任何一方发生改变,另外一方的值同步发生改变.
学会以上知识后,差不多就可以自己动手写东西了,写起来真的很方便.
播放器逻辑分析
一个简单的音乐播放器,需要有音乐播放功能,搜索音乐,显示专辑封面,显示评论,播放mv功能.
搜索音乐
需要通过双向绑定
v-model
将input
的值和data里的值绑定起来,通过读取输入值,将输入值通过axios
传给接口,然后在回调函数里将接口返回的值push到列表中,搜索音乐功能完成.音乐播放
在前面得到音乐列表后,在播放器页面中打印出来,用到了
v-bind
来绑定数据,然后需要一个播放按钮和一个mv按钮,因为不是每首歌曲都有mv,所以需要在mv按钮中添加v-show
,给一个初值为布尔值,如果mvid不为0,则有mv,这个时候将值改为true即可实现效果.显示专辑封面
这个部分很简单,只需要通过接口得到歌曲的图片,然后在特定区域显示出来即可.
显示评论
这个部分要读取用户的头像,用户名和评论,然后通过elemengt-ui提供的分隔符分开显示在右边区域即可.
播放mv
这应该是最复杂的一个部分了,本来想着播放mv时mv在页面的最前面,但是失败了,后来的解决方案是为播放器设置一个v-show
属性,当mv在播放时,则不显示播放器的主页面即可.最后的效果是这样,写了一下午,还是比较满意的.简单美化了一下.
下面是代码,比较长(主要是css太多了):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<div id="player" v-show="isShow">
<div id="playerTitle">
<p id="title">kale's player</p>
<input id="search" type="text" @keyup.enter="searchMusic()" v-model="musicName">
<button id="searchButton" type="button" @click="searchMusic()">搜索</button>
</div>
<div id="playerBody">
<div id="leftList">
<ul id="songsList">
<li id="list" v-for="item in musicList">
<i class="el-icon-video-play" @click="playerMusic(item.id)"></i>
{{ item.name }}
<i class="el-icon-video-camera-solid" @click="playerMv(item.mvid)" v-show="item.mvid!=0"
class="mvButton"></i>
<el-divider></el-divider>
</li>
</ul>
</div>
<div id="cover">
<img :src="picUrl" alt="">
</div>
<div id="comments">
<ul id="commentsList">
<li v-for="item in comments">
<img :src="item.user.avatarUrl" alt="" class="userAvatar">
<p v-text="item.user.nickname"></p>
{{ item.content }}
<el-divider></el-divider>
</li>
</ul>
</div>
</div>
<div id="playerButton">
<audio ref="audio" :src="musicUrl" controls loop class="myaudio" id="audio" autoplay="autoplay"></audio>
</div>
</div>
<div id="mvVideo" v-show="mvIsShow" class="video_con" @click="hidden()">
<video :src="mvUrl" controls="controls" autoplay="autoplay"></video>
</div>
</div>
</body>
<script>
var vue = new Vue({
el: "#app",
data: {
musicName: "",
musicId: "",
musicUrl: "",
picUrl: "",
mvUrl: "",
mvIsShow: false,
isShow: true,
musicList: [],
comments: [],
},
methods: {
searchMusic() {
var that = this
axios.get("https://autumnfish.cn/search?keywords=" + this.musicName)
.then(function (response) {
console.log(response)
that.musicList = []
for (var i = 0; i < response.data.result.songs.length; i++) {
that.musicList.push(response.data.result.songs[i.toString()])
}
},
function (err) {
console.log(err)
})
},
playerMusic(musicID) {
var that = this
axios.get("https://autumnfish.cn/song/url?id=" + musicID)
.then(function (response) {
that.musicUrl = response.data.data[0].url
},
function (err) {
console.log(err)
})
axios.get("https://autumnfish.cn/song/detail?ids=" + musicID)
.then(function (response) {
that.picUrl = response.data.songs[0].al.picUrl
},
function (err) {
console.log(err)
})
axios.get("https://autumnfish.cn/comment/hot?type=0&id=" + musicID)
.then(function (response) {
console.log(response)
that.comments = []
for (var i = 0; i < response.data.hotComments.length; i++) {
that.comments.push(response.data.hotComments[i.toString()])
}
},
function (err) {
console.log(err)
})
},
playerMv(mvId) {
var that = this
axios.get("https://autumnfish.cn/mv/url?id=" + mvId)
.then(function (response) {
that.mvIsShow = true
that.isShow = false
that.mvUrl = response.data.data.url
},
function (err) {
console.log(err)
})
},
hidden() {
this.mvIsShow = false
this.isShow = true
}
}
})
</script>
<style>
#app {
width: 100%;
height: 100%;
}
#player {
position: absolute;
width: 1200px;
height: 800px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-image: linear-gradient(to top, #fff1eb 0%, #ace0f9 100%);
}
#playerTitle {
position: absolute;
width: 100%;
height: 10%;
}
#playerBody {
position: absolute;
width: 100%;
height: 80%;
top: 10%;
}
#leftList {
position: absolute;
width: 30%;
height: 100%;
border-top: 1px solid rgb(196, 196, 196);
border-right: 1px solid rgb(196, 196, 196);
border-top-right-radius: 10px;
}
#cover {
position: absolute;
width: 40%;
height: 100%;
left: 30%;
}
#comments {
position: absolute;
width: 30%;
height: 100%;
left: 70%;
border-top: 1px solid rgb(196, 196, 196);
border-left: 1px solid rgb(196, 196, 196);
border-top-left-radius: 10px;
}
#search {
position: absolute;
width: 300px;
height: 40px;
left: 80%;
top: 50%;
padding-left: 20px;
transform: translate(-50%, -50%);
background-color: #dcf4ff;
border: none;
border-radius: 100px;
outline: none;
}
#searchButton {
position: absolute;
width: 60px;
height: 40px;
left: 92%;
top: 50%;
transform: translate(-50%, -50%);
color: black;
background-color: #dcf4ff;
border-radius: 100px;
border: none;
outline: none;
}
#playerButton {
position: absolute;
width: 100%;
height: 10%;
top: 90%;
background-color: #F1F3F4;
}
#songsList {
position: absolute;
width: 95%;
left: -10%;
height: 100%;
overflow: auto;
}
#audio {
position: absolute;
width: 100%;
height: 100%;
top: 40%;
outline: none;
left: 50%;
transform: translate(-50%, -50%);
}
li {
list-style: none;
}
img {
position: absolute;
width: 65%;
height: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 100%;
}
#commentsList {
position: absolute;
width: 85%;
height: 100%;
overflow: auto;
}
.userAvatar {
position: relative;
width: 40px;
height: 40px;
left: 0%;
top: 100%;
border-radius: 100%;
}
.mvButton {
position: absolute;
left: 85%;
}
#myVideo {
position: absolute;
width: 100%;
height: 100%;
background-color: black;
}
#title {
padding-left: 50px;
font-size: 25px;
}
</style>
</html>
- 本文标题:用vue.js写一个简单的音乐播放器
- 本文作者:Kale
- 创建时间:2020-02-12 23:44:15
- 本文链接:https://kalew515.com/2020/02/12/用vue.js写一个简单的音乐播放器/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!