Music And Video Player With VueJS | Day 2 & 3 [30 Days Of Code]
Tags: music, video, player, vue
Published: 2017-12-05 05:53:35

---
title: Music And Video Player With VueJS | Day 2 & 3 [30 Days Of Code]
published: true
description: 30 days of code
tags: music, video, player, vue
---

Hello guys, I've been gone for a bit after writing the first technical article for the first project in my 30 days of code challenge.

I'm back now and I'm writing about the two projects I covered on the second and third days.

These projects may seem a bit rushed because I was quite occupied at the time but I'm going to write about them anyway 🔥

The source code for the music player is available here on [Github](https://github.com/Jordanirabor/vueMusicPlayer/)

The source code for the video player is available here on [Github](https://github.com/Jordanirabor/vueVideoPlayer/)

#Building A Basic Music Player With VueJS

VueJS is an awesome JS library, it takes away the stress and simply makes everything cooler to do.

Here's a visual representation of the final results of the music player:

![](https://thepracticaldev.s3.amazonaws.com/i/2ux4dvts1rf5bsodpawm.png)

![](https://thepracticaldev.s3.amazonaws.com/i/qo4ws7tpczu2jzhc7psl.jpeg)

Enough talk, let's start building!

##Setup VueJS

For the sake of this tutorial, we will be using the Vue CLI for installation and setup, an alternative would be to reference Vue from a CDN 

```BASH
 https://unpkg.com/vue 
```

We can install the Vue CLI with this command:

```BASH
$ npm install --global vue-cli
```

Next, let's create a new project:

```BASH
$ vue init webpack-simple vueMusicPlayer
```

After responding to a few terminal prompts, we would have set everything up.

Let's navigate into the working directory, install dependencies and start our application:

```BASH
$ cd vueMusicPlayer
$ npm install
$ npm run dev
```
## Defining The Vue Components

For this application, we will be defining two components, the first will display the song's thumbnail and music frame at the left side of the screen while the other component will hold the playlist at the right side of the screen.

First, let's create a `components` folder in the `src` directory [ it's not necessary to do this but I like keeping a clean working directory ].

Next, we create the two components in the `components` directory. We will call them:

```BASH
musicFrame.vue

playList.vue
```

The logic behind the components of this music player is: 

> The root component [ App.vue ] holds both children components [ musicFrame and playList ] and listens for the events they emit from time to time. Whenever a song in the playlist [ to the right ] is clicked on, the root component catches a new event [ also with some data ] and updates the variables that represent the current song playing.

Great!

## Building The MusicFrame Component

Let's take a quick look at the template structure for the musicFrame component:

```HTML
<template>

<div id="musicframe">

<div id="border">

<img v-bind:src="currentImage" width="100%" height="100%"/>

<div id="controls" @click="audioFunction">

<audio ref="audio" id="audio">

<source v-bind:src="currentSong">

Your browser does not support the audio element.

</audio>
<button>Play</button>
<button>Pause</button>

</div>

</div>
</div>

</template>
```

The `musicFrame` has a wrapping `div` tag with the class "musicFrame", within this tag, there is a border `div` tag that shelters other internal tags. 

An `<img/>` tag sits directly below the border tag, it has the value of its 'src' attribute bound to a `currentImage` Vue variable [ this variable updates the song's thumbnail whenever a new song is selected ].

Now, for the more obvious part, a `div` tag with an id of "controls" wraps the HTML5 audio element, it also listens for `onclick` functions and calls an `audioFunction` function as a handler.

Cool!

The <audio/> tag takes a `ref` [ it will help address the tag specifically ] while the nested <source/> tag has a dynamic `src` attribute to allow dynamic music behavior.

That was pretty tiring to go into detail with, let's see what the innards of the script tag hold.

```JS
<script>
import { bus } from '../main';
export default {
  name: 'music-frame',
props : {
 
 currentSong: {
  type : String
 },
 currentImage: {
  type : String
 }
  },
  data () {
    return {
    }
  },
  methods: {
    audioFunction: function(e){
      let value = e.target.innerText;
      switch(value) {
        case "Play" : {
              console.log(this.$refs.audio.play());
              break;
        }
        case "Pause" : {
              this.$refs.audio.pause();
              break;              
        }
      }
    }
  },
  created(){
    bus.$on('reload', () => {
    this.$refs.audio.load();
    this.$refs.audio.play();
    })
  }
}
</script>
```

Well, for this bit, it isn't as complicated as it may appear at first. Let's go.

Firstly, we are importing a bus [ this is just an instance of a Vue object defined on the global `main.js` file ] because we need it to drive events and data between the children components [ musicFrame and playList ].

After exporting default [ creating a reusable module ], we reach out and receive `props` from the root component [ App.vue ]. In this component, we will not be registering any variable [ it's the reason the data function returns an empty object].

Next, we register the single `audioFunction` method, this is the method called by the `controls` div whenever any of its `<button/>` children are clicked. This method pipes the `innerText` on the target element through a `switch` statement and is able to toggle media controls e.g play, pause etc

Lastly, we attach a live cycle hook to this component, this hook fires as soon as the application is created. It's objective is to listen for a `reload` on the imported bus [ from the playList component ] and play a song whenever that event is caught [ this is the logic that helps to ensure that a new song is played when selected].

That's everything with the musicFrame component.

## Building The PlayList Component

Like the previous component, let's begin by examining the template structure: 

```HTML
<template>

  <div id="playlist">

    <div id="secborder" ref="playlist" @click="changeSource">

    <div class="song" url-value="http://sami-server.info/hossein2/95/11/Music/06/Ed%20Sheeran%20-%20Shape%20Of%20You.mp3" picture-value="https://www.billboard.com/files/media/ed-sheeran-july-2017-billboard-1548.jpg"> Ed Sheeran  &nbsp;∘ &nbsp; Shape of you </div>
    <div class="song" url-value="http://jweb.taconic.net/music/linkin_park-faint.mp3" picture-value="https://orig00.deviantart.net/65e3/f/2009/335/6/2/linkin_park__faint_by_jimeye.jpg">Linkin Park &nbsp;∘&nbsp; Faint</div>
    <div class="song" url-value="http://dl.asra-music.com/foreign%20full%20album/Pink/Pink%20-%20The%20Truth%20About%20Love%20(2012)/04%20-%20Just%20Give%20Me%20A%20Reason.mp3" picture-value="https://i.ytimg.com/vi/3pDj1U6Zd08/maxresdefault.jpg">Pink &nbsp;∘&nbsp; Just give me a reason</div>
    <div class="song" url-value="http://tegos.kz/new/mp3_full/Clean_Bandit_-_Symphony.mp3" picture-value="https://i.ytimg.com/vi/jtTI-XuW8i8/maxresdefault.jpg"> Clean Bandit &nbsp;∘&nbsp; Symphony</div>    <div class="song" url-value="http://zaycev-mp3.net/mp3/linkin_park_powerless_[zaycev-mp3.net].mp3" picture-value="https://wallpapercave.com/wp/ufT9VZa.jpg">Linkin Park &nbsp;∘&nbsp; Powerless</div>
    <div class="song" url-value="http://rm.sina.com.cn/wm/VZ2008072314565310537VK/music/MUSIC0807231507294087.mp3" picture-value="https://i.ytimg.com/vi/oY5BYjsrIHk/maxresdefault.jpg">Linkin Park &nbsp;∘&nbsp; Somewhere I belong</div>
    <div class="song" url-value="http://s4.faz-dl.xyz/mr-reese/single/july2017/week1/Rihanna%20-%20Wild%20Thoughts%20Solo%20Version%20-%20MP3%20320.mp3" picture-value="http://thetropixs.com/wp-content/uploads/2017/06/Rihanna-Wild.jpg"> Rihanna &nbsp;∘&nbsp; Wild thoughts</div>
    <div class="song" url-value="http://a.tumblr.com/tumblr_mirhiitqaC1roewk4o1_r1.mp3" picture-value="https://i.ytimg.com/vi/vAsztnDeZ1Q/maxresdefault.jpg">Demi Lovato &nbsp;∘&nbsp; Heart Attack</div>
    <div class="song" url-value="https://70mack.co/wp-content/upload/2017/10/Davido_FIA.mp3" picture-value="https://3.bp.blogspot.com/-J7w5lyePAfw/WgbF1knkwJI/AAAAAAAAVdI/t2ZOSjmLtssuxuT-czWbETE-hc2DC9wIACK4BGAYYCw/w1200-h630-p-k-no-nu/Davido%2BFia.png"> Davido &nbsp;∘&nbsp; FIA</div>    
    <div class="song" url-value="http://img0.liveinternet.ru/images/attach/b/3/3656/3656927_eminem__mockingbird.mp3" picture-value="https://wallpapercave.com/wp/WlHnNj6.jpg">Eminem &nbsp;∘&nbsp; Mocking Bird</div>    

    </div>


  </div>

</template>
```

Messy stuff. I know.


The template for this component is pretty straightforward, it's just a bunch of `<div/>` tags holding custom attributes: `url-value` and `picture-value`, we need these values to supply the <audio/> and <img/> tags with dynamic data whenever a song [div] in the playlist is clicked.

Next, the `<script/>` section:

```JS
<script>
import { bus } from '../main';
export default {
  name: 'playlist',
  props : {
 
 currentSong: {
  type : String
 },
 currentImage: {
  type : String
 }
  },
  data () {
    return {
    }
  },
  
  methods: {
    changeSource : function(e) {
      let songValue = e.target.attributes[1].value;
      let songImage = e.target.attributes[2].value;
      this.$emit('updateData', [songValue, songImage]);
      bus.$emit('reload');
    }
  }
}
</script>
```

Remember that bus the previous component imported? Yes. That bus, this component has to import it too so there is a medium for communication between the both of them.

In the next steps, we do a few basic things like receiving `props` from the root component, not declaring any variables [ and it's not because we are too cheap to afford one ].

Lastly, we declare a method, the `ChangeSource` and its job is quite as its name says:

This method gets the new values [URL for song and image] from the selected song [div] in the playlist, emits an event to the root method [ with the two values earlier retrieved]. This method also emits a 'reload' event using the `bus`.

Awesome.

## And Now For The Root Component

The root component is responsible for coordinating the data that runs between the two children component and making sense out of it. Let's see what this component has under the carpet.

As usual, the template section is examined first:

```HTML
<template>

<div id="app">

<videoframe v-bind:currentVideo="currentVideo"></videoframe>

<playlist v-bind:currentVideo="currentVideo" @updateData="swapData($event)"></playlist>

</div>

</template>
```

Unlike the other two components, the root component has its template in a nice, precise and concise fashion. A root `div` tag with an id "app" wraps the two nested children components.

The children components have two variables bound to their dynamic attributes.On playlist, the root component listens for an "updateData" event and handles it with a "swapData" function.

Nice, precise and concise.

Time for a peek at the script:

```JS

<script>
import videoframe from './components/videoFrame'
import playlist from './components/playList'
export default {
  name: 'app',
  components: {
  'videoframe' : videoframe,
  'playlist' : playlist
},
  data () {
    return {
      currentVideo : ''
    }
  },
  methods: {
    swapData: function(data) {
     this.currentVideo = data;
    }
  }
}
</script>

```

First, we import `musicFrame` and `playList` [obviously because we need them], then we register them as components.

We define two `key/value` pairs in the data function, the first one will hold data for the current song playing, while the other will at first hold a default image banner for the musicFrame banner and alter adopt thumbnails dynamically.

Lastly, we define a single method called `swapData`, this method receives the data emitted in an event from a child component child and toggles values dynamically.

Awesome 🔥 

That's all for the music player app, now it's time for the video player.

Here's a visual representation of the music player application we will be creating:

![](https://thepracticaldev.s3.amazonaws.com/i/0p6fp8s6r9c6gpdp8g53.png)

![](https://thepracticaldev.s3.amazonaws.com/i/j2ya1hls9zu2p6xhj8kt.png)

I would also go deep into explaining the video player application but the truth is, it is really similar to the music player application in logic, so there really isn't any need.


#Conclusion

Awesome! 🔥 That is all it takes to build a music player and video player in VueJS.

I may have left a bit of the actual code out this article for brevity purposes.


To run these projects locally, type in the following commands in a terminal.


```
-- clone the repository --

git clone https://github.com/Jordanirabor/vueMusicPlayer

OR

git clone https://github.com/Jordanirabor/vueVideoPlayer


-- navigate into the directory --

cd vueMusicPlayer

OR

cd vueVideoPlayer

-- install dependencies --

npm install 

-- serve with hot reload at localhost:8080 --

npm run dev

-- build for production with minification --

npm run build
```



I'll be building and writing about another project tomorrow, stay tuned 🔥🔥🔥