
使用Vue.js构建应用程序非常容易,有趣且令人愉快。 您可以以最少的精力构建可运行的应用程序。 为了证明这一点,今天我将向您展示构建自己的功能齐全的音乐播放器有多么容易。 为了使事情变得更加简单,我们将使用Vuetify.js (一种由Vue.js驱动的UI库),它将加快UI的构建。 我几乎可以感觉到您的不耐烦,所以让我们开始吧。
您可以在GitHub repo中找到完整的源代码。 这是工作演示 。 要遵循本教程,您应该熟悉Vue组件 , Vue单个文件组件和ES2015语法 。
规划应用
每个创意都始于一个想法,至少是一些基本计划。 因此,首先我们需要决定要构建什么以及要实现什么功能。 据说一张图片值一千个字,所以让我们从音乐播放器的简单草图开始。

我制作了此线框,以便您可以大致了解我们要构建的UI。 下一步是描述我们打算实现的功能。
正如约翰逊(John Johnson)所说:
首先,解决问题。 然后,编写代码。
我们将其用作智慧的来源,并且在开始编写应用程序之前会对其进行规划。
应用组件
Vue.js是一个基于组件的框架。 因此,我们首先需要将应用拆分为各个组件(在我们的示例中为五个组件,如上图所示),并概述每个组件的功能。
标题栏
该组件将包含以下部分:
- 左侧的菜单
- 中间应用程序的名称
- 右侧的三个静态图标
信息面板
此组件将显示有关当前播放曲目的基本信息:
- 曲目的艺术家和标题在左侧
- 当前曲目的位置和持续时间在右侧
控制杆
该组件将包含两个栏,其中包括操纵播放器播放列表中的音轨所需的所有控件。
- 左侧带有图标的音量滑块(其外观会根据音量级别和声音静音而改变),右侧为音量百分比
- 用于播放,暂停,停止和跳过曲目的按钮。
- 最右边的两个按钮:一个用于重复播放当前曲目,另一个用于重新排列曲目的播放顺序
- 查找栏,显示当前播放的曲目的位置,并能够通过鼠标单击更改它
播放列表面板
该组件将包含具有以下功能的曲目的播放列表:
- 显示具有正确编号,艺术家,标题和时长属性的曲目
- 一键选择曲目
- 双击播放曲目
搜索栏
当我们要查找和播放特定曲目时,此组件将提供搜索功能。
当然,以上概述不能涵盖所有细节和细微差别,这很好。 到目前为止,对于我们而言,获得最终产品的总体情况就足够了。 在构建过程中,我们将处理所有细节和最终挑战。
因此,让我们进入有趣的部分并编写一些代码!
入门
Vuetify的快速入门页面提供了很多选择来帮助您入门。 我们将使用一种称为Webpack Simple的预制Vue CLI模板。 在要用于此项目的目录中运行以下命令:
首先,安装Vue CLI:
$ npm install -g vue-cli
然后,创建应用程序:
$ vue init vuetifyjs/webpack-simple vue-music-player
接下来,转到应用程序的目录并安装所有依赖项:
$ cd vue-music player
$ npm install
我们将使用Howler.js (JavaScript音频库)来处理音乐播放器的音频部分。 因此,我们也需要将其包括在项目中。 运行以下命令:
$ npm install --save howler
最后,运行该应用程序:
$ npm run dev
该应用程序将在默认浏览器的localhost:8080
上打开。 您应该会看到一个简单的Vuetify应用程序框架。
调整模板
为了适应我们的需求,我们需要清理模板并对其进行一些调整。 将App.vue文件重命名为Player.vue ,将其打开,删除其中的所有内容,然后添加以下内容:
<template>
<v-app dark>
<v-content>
<v-container>
<!-- The player components go here -->
</v-container>
</v-content>
</v-app>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>
我们将音乐播放器应用程序包装在v-app
组件中,这是该应用程序正常运行所必需的。 我们还通过了dark
道具,以应用Vuetify深色主题。
现在,打开main.js文件,删除原始内容,然后添加以下内容:
import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.css'
import Player from './Player.vue'
import {Howl, Howler} from 'howler'
Vue.use(Vuetify)
new Vue({
el: '#app',
render: h => h(Player)
})
另外,打开index.html文件,并将<title>
标记的内容更改为Vue Music Player 。
现在,在浏览器中,您应该看到一个空白的暗页。 和瞧。 您已准备好开始创建。
在开始编码之前,最好知道Vuetify为主要代码编辑器(VS Code,Atom和Sublime)提供了代码片段和自动补全功能。 要获取代码片段,请在您喜欢的编辑器( vuetify-vscode
或vuetify-atom
或vuetify-sublime
)中搜索扩展名。
构建标题栏组件
在src目录中,创建一个新的components文件夹。 然后,在该文件夹中,创建具有以下内容的PlayerTitleBar.vue文件:
<template>
<v-system-bar window>
<v-menu offset-y transition="slide-y-transition">
<v-btn flat small right slot="activator">
<v-icon>headset</v-icon> MENU
</v-btn>
<v-list>
<v-list-tile @click="dialog = true">
<v-list-tile-title>About</v-list-tile-title>
</v-list-tile>
<v-dialog v-model="dialog" max-width="300">
<v-card>
<v-card-title><h2>Vue Music Player</h2></v-card-title>
<v-card-text>Version 1.0.0</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn flat @click="dialog = false">OK</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-list>
</v-menu>
<v-spacer></v-spacer>
VUE MUSIC PLAYER
<v-spacer></v-spacer>
<v-icon>remove</v-icon>
<v-icon>check_box_outline_blank</v-icon>
<v-icon>close</v-icon>
</v-system-bar>
</template>
<script>
export default {
data () {
return {
dialog: false
}
},
}
</script>
在这里,我们使用以下Vuetify组件: 工具栏 , 菜单 , 按钮 , 图标 , 列表 , 对话框和卡片 。
我们用<v-spacer>
组件将菜单,名称和图标分开。 为了显示或隐藏对话框,我们创建dialog: false
data属性。 单击关于菜单项时,其值将切换。
现在,在Player.vue文件中,导入标题栏组件,将其注册在components对象中,然后将其添加到模板中。
<template>
<v-app dark>
<v-content>
<v-container>
<player-title-bar></player-title-bar> // ADD the component in the template
</v-container>
</v-content>
</v-app>
</template>
<script>
import PlayerTitleBar from './components/PlayerTitleBar.vue' // IMPORT the component
export default {
components: {
PlayerTitleBar // REGISTER the component
},
data () {
return {
}
}
}
</script>
现在,在浏览器中检查结果。 您应该看到以下内容:

我们将对其他四个组件重复这三个步骤。 因此,当我在下一节中告诉您要在模板中导入,注册和添加组件时,您应遵循此处描述的相同过程。
构建播放列表组件
在根目录中,创建一个新的播放列表文件夹,然后添加要播放的音频文件。 文件名必须在单词之间加上下划线,并以.mp3扩展名结尾,例如, Remember_the_Way.mp3 。 现在,在Player.vue的数据对象中创建一个音轨数组:
playlist: [
{title: "Streets of Sant'Ivo", artist: "Ask Again", howl: null, display: true},
{title: "Remember the Way", artist: "Ask Again", howl: null, display: true},
...
]
每个轨道都有title
和artist
属性,将howl
对象设置为null
,并将display
属性设置为true
。
当我们实现搜索功能时,将使用display
属性。 现在,所有轨道都设置为true
,因此所有轨道都可见。
ler叫器将音频文件包装在a howl
对象中。 我们将howl
设置为null
因为我们将在创建Vue实例时动态填充它。 为此,我们使用Vue created
生命周期hook 。
created: function () {
this.playlist.forEach( (track) => {
let file = track.title.replace(/\s/g, "_")
track.howl = new Howl({
src: [`./playlist/${file}.mp3`]
})
})
}
这将为播放列表中的每个轨道设置一个新的Howl
对象。
现在,创建PlayerPlaylistPanel.vue组件并将其添加到内部:
<template>
<v-card height="330">
<v-list>
<v-list-tile
v-for="(track, index) in playlist"
:key="track.title"
v-show="track.display">
<v-list-tile-content>
<v-list-tile-title>{{ index }} {{ track.artist }} - {{ track.title }}</v-list-tile-title>
</v-list-tile-content>
<v-spacer></v-spacer>
{{ track.howl.duration() }}
</v-list-tile>
</v-list>
</v-card>
</template>
<script>
export default {
props: {
playlist: Array
}
}
</script>
首先,我们从Player.vue文件传递道具playlist
。 接下来,在模板中,我们使用v-for
指令遍历每个轨道,并显示轨道的索引,然后是轨道的艺术家和标题,以及轨道的持续时间在最右边。 我们还使用绑定到display
属性的v-show
。 仅当display
为true
轨道才可见。
现在,在Player.vue文件中,我们导入,注册并在模板中添加播放列表组件。 然后,将playlist
prop绑定到playlist
playlist
数据属性,如下所示: <player-playlist-panel :playlist="playlist"></player-playlist-panel>
。
让我们在浏览器中检查结果:

这里有两个问题。 首先,磁道的数量不正确,其次,磁道的持续时间以毫秒为单位显示,但我们希望以分钟为单位。 我们将通过创建格式过滤器来解决所有这些问题。
在main.js文件中,创建可全局访问的numbers
过滤器和minutes
过滤器。 接下来,在PlayerPlaylistPanel.vue中 ,我们像这样使用它们: {{ index | numbers }}
{{ index | numbers }}
和{{ track.howl.duration() | minutes }}
{{ track.howl.duration() | minutes }}
。
现在,如果您检查应用程序,则所有内容都应正确显示。

使轨道可选
在Player.vue文件中,添加selectedTrack: null
数据属性并将其绑定到播放列表组件( :selectedTrack="selectedTrack"
)。 然后,将属性传递到PlayerPlaylistPanel.vue文件( selectedTrack: Object
)中。
我们还将单击事件侦听器添加到<v-list-tile-content @click="selectTrack(track)">
,然后创建selectTrack()
方法:
methods: {
selectTrack (track) {
this.$emit('selecttrack', track)
}
}
现在,回到Player.vue
,将selecttrack
事件添加到播放列表组件( @selecttrack="selectTrack"
)并创建selectTrack()
方法:
selectTrack (track) {
this.selectedTrack = track
}
现在,如果您转到播放列表并单击曲目,它将被选中。 我们看不到它,但是我们可以在Vue DevTools中证明它。 在以下屏幕截图中,选择了第二条轨道:

行和选择样式
下一步是使选择可见。 为此,我们将绑定一个类,该类将为选定的轨道着色为橙色,而另一个类将使行更暗,以使轨道更容易区分。 将以下内容放在v-show
指令之后:
:class="[{selected: track === selectedTrack}, {even: index % 2 == 0}]"
我们还将添加另一个类,当列表太大时将显示一个滚动条。
<v-card height="330" :class="{playlist}">
我们在文件末尾添加必要的类。
<style scoped>
.selected {
background-color: orange !important;
}
.even {
background-color: #505050
}
.playlist {
overflow: auto
}
</style>
就是这样。 现在,所选曲目以橙色突出显示。

我们将在下一部分的末尾添加双击播放功能。
构建播放器控件组件
现在创建播放器控件。 我们将从播放,暂停和停止按钮开始。
添加播放,暂停和停止按钮
创建PlayerControlsBars.vue组件并将其添加到内部:
<template>
<div>
<v-toolbar flat height=90>
<v-spacer></v-spacer>
<v-btn outline fab small color="light-blue" @click="stopTrack">
<v-icon>stop</v-icon>
</v-btn>
<v-btn outline fab color="light-blue" @click="playTrack()">
<v-icon large>play_arrow</v-icon>
</v-btn>
<v-btn outline fab small color="light-blue" @click="pauseTrack">
<v-icon>pause</v-icon>
</v-btn>
<v-spacer></v-spacer>
</v-toolbar>
</div>
</template>
在这里,我们使用Vuetify 工具栏组件。
具有注册的单击事件侦听器的三个按钮。 让我们为他们创建方法:
methods: {
playTrack(index) {
this.$emit('playtrack', index)
},
pauseTrack() {
this.$emit('pausetrack')
},
stopTrack() {
this.$emit('stoptrack')
}
}
现在,在Player.vue文件中,导入,注册组件并将其添加到模板中。 然后,注册事件侦听器( @playtrack="play"
, @pausetrack="pause"
, @stoptrack="stop"
)。
接下来,创建index: 0
数据属性,该属性将保存当前轨道的索引。 然后,创建一个计算的currentTrack()
:
computed: {
currentTrack () {
return this.playlist[this.index]
}
}
现在,我们可以开始创建play
, pause
和stop
方法。 我们将从play()
方法开始,但是在此之前,我们需要创建playing: false
数据属性,该属性将指示轨道是否正在播放。 为play()
方法添加以下代码:
play (index) {
let selectedTrackIndex = this.playlist.findIndex(track => track === this.selectedTrack)
if (typeof index === 'number') {
index = index
} else if (this.selectedTrack) {
if (this.selectedTrack != this.currentTrack) {
this.stop()
}
index = selectedTrackIndex
} else {
index = this.index
}
let track = this.playlist[index].howl
if (track.playing()) {
return
} else {
track.play()
}
this.selectedTrack = this.playlist[index]
this.playing = true
this.index = index
}
该方法以索引作为参数,该索引指定要播放的曲目。 首先,我们获得所选曲目的索引。 然后,我们进行一些检查以确定index
的值。 如果提供索引作为参数,并且它是一个数字,那么我们将使用它。 如果选择了轨道,我们将使用选定轨道的索引。 如果所选轨道与当前轨道不同,则使用stop()
方法停止当前轨道。 最后,如果既未传递索引参数也未选择轨道,则将使用index
数据属性的值。
接下来,我们获取曲目的l叫声(基于索引值),并检查它是否正在播放。 如果是这样,我们什么也不会返回。 如果不是,我们玩。
最后,我们更新selectedTrack
, playing
和index
数据属性。
现在让我们创建pause()
和stop()
方法。
pause () {
this.currentTrack.howl.pause()
this.playing = false
},
stop () {
this.currentTrack.howl.stop()
this.playing = false
}
在这里,我们只是暂停或停止当前曲目并更新playing
数据属性。
让我们同时双击开始播放曲目。
添加@dblclick="playTrack()"
以<v-list-tile-content>
在PlayerPlaylistPanel.vue并创建playTrack()
方法:
playTrack(index) {
this.$emit('playtrack', index)
}
在Player.vue文件中注册监听器@playtrack="play"
,瞧。
添加上一个和下一个按钮
现在,我们添加上一个和下一个按钮。
<v-btn outline fab small color="light-blue" @click="skipTrack('prev')">
<v-icon>skip_previous</v-icon>
</v-btn>
<!-- stop, play, and pause buttons are here -->
<v-btn outline fab small color="light-blue" @click="skipTrack('next')">
<v-icon>skip_next</v-icon>
</v-btn>
创建skipTrack()
方法:
skipTrack (direction) {
this.$emit('skiptrack', direction)
}
在Player.vue中注册事件侦听器( @skiptrack="skip"
)。
并创建skip()
方法:
skip (direction) {
let index = 0
if (direction === "next") {
index = this.index + 1
if (index >= this.playlist.length) {
index = 0
}
} else {
index = this.index - 1
if (index < 0) {
index = this.playlist.length - 1
}
}
this.skipTo(index)
},
skipTo (index) {
if (this.currentTrack) {
this.currentTrack.howl.stop()
}
this.play(index)
}
我们首先检查方向是否是next
。 如果是这样,我们将索引增加1。如果索引大于数组中的最后一个索引,那么我们将从零开始。 当方向为prev
,我们将索引减1。如果索引小于零,则使用最后一个索引。 最后,我们将index
用作skipTo()
方法的参数。 它将停止当前曲目并播放下一个或上一个。
播放器的按钮外观如下:

添加音量滑块
在所有按钮之前添加以下内容:
<v-slider v-model="volume" @input="updateVolume(volume)" max="1" step="0.1"></v-slider>
在这里,我们使用Vuetify 滑块组件。
添加volume: 0.5
数据属性,然后创建updateVolume()
方法:
updateVolume (volume) {
Howler.volume(volume)
}
在这里,我们使用全局咆哮对象为所有啸声全局设置音量。
另外,我们需要将初始咆哮音量(默认设置为1)同步到volume
属性。 如果不这样做,音量将显示为0.5,但最初为1。 为此,我们将再次使用created
钩子:
created: function () {
Howler.volume(this.volume)
}
我们想在音量滑块的右侧看到音量水平,因此我们将其添加到模板中: {{this.volume * 100 + '%'}}
添加静音按钮
现在,我们在滑块之前添加一个音量图标。
<v-btn flat icon @click="toggleMute">
<template v-if="!this.muted">
<v-icon v-if="this.volume >= 0.5">volume_up</v-icon>
<v-icon v-else-if="this.volume > 0">volume_down</v-icon>
<v-icon v-else>volume_mute</v-icon>
</template>
<v-icon v-show="this.muted">volume_off</v-icon>
</v-btn>
图标将根据volume
和muted
属性的值而变化。
添加muted: false
数据属性,并创建toggleMute()
方法:
toggleMute () {
Howler.mute(!this.muted)
this.muted = !this.muted
}
我们再次使用全局咆哮对象来全局设置静音,然后切换muted
值。
在下面的屏幕截图中,您可以看到音量滑块的外观:

添加重复按钮
在所有按钮之后添加以下内容:
<v-btn flat icon @click="toggleLoop">
<v-icon color="light-blue" v-if="this.loop">repeat_one</v-icon>
<v-icon color="blue-grey" v-else>repeat_one</v-icon>
</v-btn>
在Player.vue中添加loop: false
属性,将其绑定到:loop="loop"
并在PlayerControlsBars.vue中传递prop( loop: Boolean
)。
现在,让我们创建toggleLoop()
方法:
toggleLoop () {
this.$emit('toggleloop', !this.loop)
}
现在,返回Player.vue ,注册事件侦听器( @toggleloop="toggleLoop"
)并创建toggleLoop()
方法:
toggleLoop (value) {
this.loop = value
}
在这一点上,我们面临一个小问题。 当轨道寻找终点时,它就停止了。 播放器不会移动到下一曲目,也不会重复当前曲目。 为了解决这个问题,我们需要在src
属性之后将以下内容添加到created
函数中:
onend: () => {
if (this.loop) {
this.play(this.index)
} else {
this.skip('next')
}
}
现在,当loop
打开时,将重复当前曲目。 如果关闭,则播放器将移至下一首曲目。
添加随机播放按钮
在重复按钮之后添加以下内容:
<v-btn flat icon @click="toggleShuffle">
<v-icon color="light-blue" v-if="this.shuffle">shuffle</v-icon>
<v-icon color="blue-grey" v-else>shuffle</v-icon>
</v-btn>
在Player.vue
添加shuffle: false
属性,将其绑定( :shuffle="shuffle"
),然后在PlayerControlsBars.vue
传递prop( shuffle: Boolean
)。
现在,让我们创建toggleShuffle()
方法;
toggleShuffle () {
this.$emit('toggleshuffle', !this.shuffle)
}
现在,返回Player.vue ,注册事件侦听器( @toggleshuffle="toggleShuffle"
)并创建toggleShuffle()
方法:
toggleShuffle (value) {
this.shuffle = value
}
现在,在index = 0
之后将以下内容添加到skip()
方法中:
lastIndex = this.playlist.length - 1
if (this.shuffle) {
index = Math.round(Math.random() * lastIndex)
while (index === this.index) {
index = Math.round(Math.random() * lastIndex)
}
} else if (direction === "next") { ...
现在,您的应用应如下所示:

添加搜索栏
首先,在Player.vue中 ,创建seek: 0
属性。 然后,我们需要观看playing
属性以更新搜索。
watch: {
playing(playing) {
this.seek = this.currentTrack.howl.seek()
let updateSeek
if (playing) {
updateSeek = setInterval(() => {
this.seek = this.currentTrack.howl.seek()
}, 250)
} else {
clearInterval(updateSeek)
}
},
}
这将每秒更新搜索值四次。
现在,创建一个计算的progress()
:
progress () {
if (this.currentTrack.howl.duration() === 0) return 0
return this.seek / this.currentTrack.howl.duration()
}
将其绑定( :progress="progress"
)在模板中。
现在,在PlayerControlsBars.vue中 ,传递progress
道具( progress: Number
),然后在我们已经创建的工具栏下面添加另一个工具栏:
<v-toolbar flat height="40">
<v-progress-linear height="40" v-model="trackProgress" @click="updateSeek($event)"></v-progress-linear>
</v-toolbar>
在这里,我们使用Vuetify 进度组件。
创建一个计算的trackProgress()
,它将以百分比形式获取轨道的进度。
computed: {
trackProgress () {
return this.progress * 100
},
}
现在,创建updateSeek()
方法:
updateSeek (event) {
let el = document.querySelector(".progress-linear__bar"),
mousePos = event.offsetX,
elWidth = el.clientWidth,
percents = (mousePos / elWidth) * 100
this.$emit('updateseek', percents)
}
在这里,我们获得进度条元素,该元素使用.progress-linear__bar
类。 我是通过浏览器DevTools找到的。 接下来,我们获得鼠标的位置和条的宽度。 然后,我们获得鼠标点击位置百分比。
返回Player.vue中 ,添加并注册事件监听器( @updateseek="setSeek"
)并创建setSeek()
方法:
setSeek (percents) {
let track = this.currentTrack.howl
if (track.playing()) {
track.seek((track.duration() / 100) * percents)
}
}
和繁荣! 您可以使用鼠标来更改播放曲目的位置。
构建信息面板组件
创建具有以下内容的PlayerInfoPanel.vue文件:
<template>
<v-card height="60">
<v-card-title>
<h2>{{ trackInfo.artist }} - {{ trackInfo.title }}</h2>
<v-spacer></v-spacer>
<h3>{{trackInfo.seek | minutes}}/{{trackInfo.duration | minutes}}</h3>
</v-card-title>
</v-card>
</template>
<script>
export default {
props: {
trackInfo: Object
},
}
</script>
在这里,我们传递了一个trackInfo
,用于在组件中填充轨道信息。
现在,返回Player.vue ,导入,注册组件并将其添加到模板中。
然后,创建一个计算的getTrackInfo()
:
getTrackInfo () {
let artist = this.currentTrack.artist,
title = this.currentTrack.title,
seek = this.seek,
duration = this.currentTrack.howl.duration()
return {
artist,
title,
seek,
duration,
}
}
接下来,我们将其绑定到模板( :trackInfo="getTrackInfo"
)中,瞧。 您可以在下面的屏幕快照中看到有关当前播放曲目的一些基本信息。

构建搜索栏组件
创建具有以下内容的PlayerSearchBar.vue文件:
<template>
<v-toolbar flat>
<v-text-field
clearable
prepend-icon="search"
placeholder="Quick search"
v-model="searchString"
@input="searchPlaylist">
</v-text-field>
<v-spacer></v-spacer>
</v-toolbar>
</template>
<script>
export default {
props: {
playlist: Array
},
data () {
return {
searchString: "",
}
},
methods: {
searchPlaylist () {
this.playlist.forEach((track) => {
if (this.searchString) {
if (!track.title.toLowerCase().includes(this.searchString.toLowerCase()) && !track.artist.toLowerCase().includes(this.searchString.toLowerCase())) {
track.display = false
} else {
track.display = true
}
} else if (this.searchString === "" || this.searchString === null) {
track.display = true
}
})
}
},
}
</script>
我们创建一个文本字段,并添加可clearable
道具以在键入内容时显示清除图标。
通过使用v-model
,我们将其绑定到searchString
,该字符串最初是一个空字符串。 然后添加一个输入事件侦听器。
我们还传递了在searchPlaylist()
方法中使用的playlist
道具。 在这种方法中,我们使用display
属性,并把它off
各音轨在标题或艺术家不匹配搜索字符串,然后我们把它或把它on
所有比赛。 最后,如果搜索字符串为空或等于null
,当我们与清除按钮清除字段,它发生了,我们把on
的display
的所有曲目。
现在,返回Player.vue ,导入,注册组件并将其添加到模板中。
绑定播放列表属性( :playlist="playlist"
)并检查功能。 这是实际效果:

一些改进思路
如您所见,有了明确的目标和适当的计划,构建Vue / Vuetify应用程序将变得非常容易和愉快。 现在,您有了一个可以正常工作的音乐播放器,可以在放松或编码期间使用它。 当然,总会有进一步改进和增加的空间,因此您可以尝试以下一些方法,使播放器的功能更加丰富:
- 多个播放列表支持
- 从播放列表添加或删除曲目的功能
- 拖放支持
- 排序曲目的能力
- 音频可视化
结论
在本教程中,我们看到了使用Vue.js(尤其是Vuetify.js)构建应用程序是多么容易和有趣。 希望您和我一样喜欢建立这个球员。 我很高兴看到您自己改进的播放器版本。 因此,如果创建一个,只需在评论中放置一个演示链接!
翻译自: https://code.tutsplus.com/tutorials/building-a-full-featured-music-player-with-vuetify--cms-31228