What kind of app do we want to build?
Most of us use online streaming services like Netflix to watch our favorite movies or shows. This article will focus on how to create a similar style movie streaming web interface (see) using Vue.js 2.
The final product can be found here: HTTPS://CODEPEN.IO/ITSLIT/FULL/MVVJZR.
Although Bulma will act as the CSS framework for the application, But this article will mainly focus on the use of vue.js and browsing CSS style, if you want to follow the learning, I set up a can as a starting point of learning, all the custom combination, the initial data object and necessary to be referenced by the CDN external libraries (such as vue-router, etc.), can be from the https:/ /codepen.io/itslit/pen/qmzrev obtained.
Basic needs of the app
Let's write down these basic needs:
Introduction (Login) screen
Footer to allow users to choose the movie they want
A movie screen that shows the title/description of the movie and a prompt for "play Now".
A movie trailer screen that shows a movie trailer when the movie is playing.
You can add a movie to the Favorites folder
We'll create the app and let the footer appear at any time, and the home page, movie and movie trailer will share the same screen.
Data
For simplicity, we'll start with a simple/reliable data object (object) that will act as the primary memory for all of our components. This storage object will have all the movie information we need and will focus on Christopher Nolan's awesome movies. The following is part of the data object:
Const MOVIES = {"Dunkirk": {"id": ' Dunkirk ' "title": ' Dunkirk ',"subtitle": ' Dunkirk ',"description": 'miraculous evacuation of Allied soldiers from Belgium, Britain, Canada, and France, who were cut off and surrounded by The German army from the beaches and harbor of Dunkirk, France, during the Battle of France in world War ii.‘,"largeimgsrc": ' url (' https://image.tmdb.org/t/p/w780/fudEG1VUWuOqleXv6NwCExK0VLy.jpg '))`,"smallimgsrc ': ' Https://image.tmdb.org/t/p/w185/fudEG1VUWuOqleXv6NwCExK0VLy.jpg ',"ReleaseDate": ' July ',"duration": ' 1hr 46min ',"Genre": ' Action, Drama, History ',"Trailerpath": ' Https://www.youtube.com/embed/F-eMt3SrfFU ',"Favorite": false},"Interstellar": {...},"The-dark-knight-rises": {...},"Inception": {...},"The-prestige": {...}}
Let's start building apps
Now that we've created the primary storage object and understood how all of our components are laid out, we can start building the interface.
Let's first create the Vue instance. We will mount the instance to the DOM element app and return the global stored movies as part of the instance data object accessed in our HTML.
New' #app ', data () {return {moviechoices:movies} }})
We can now start working on each individual component.
Footer section
Let's start with a fixed footer section that lists all the movies in the data store.
<div id= "app" ><section class= "hero is-primary is-medium" ><div class= "Hero-foot" ><div class= " Columns Is-mobile "><div vfor =" Moviechoice in Moviechoices "class=" column "><li class=" Movie-choice "><p class=" mobile ">{{ Moviechoice.subtitle}}</p></li></div></div></div></section></div>
For the section already in the bold code snippet above:
We use the id= "app" to create DOM elements where our Vue instance will be mounted.
We are using the native v-for instruction to render the list from the data source moviechoices.
In each of the Moviechoice:
We will bind an image of src to the URL ("desktop") within the Smallimgsrc object that describes our movie.
We use mustache syntax, data binding to Moviechoice.subtitle as the phone screen text display content.
With the rendering of all CSS styles, our application should now look like this:
Desktop footer
Phone-side footer
Film Introduction components (and Vue-router)
We created the footer and now our goal is to create a movie presentation component with our app title and description.
We have mentioned that the components will share the same screen for upcoming movie trailers and components (i.e. users will be able to reach the appropriate link directly in our app by clicking Intro-to-movie-moviecomponent).
This is a perfect use case to add vue-router libraries. Vue-router is the Vue.js official router, which is a configurable router that allows components to be deeply integrated, as well as nested/view mappings and so on.
We will make basic routing settings in the JS file:
Const Intro = {Template: '<div class= ' hero-body "style=" background: #1e1d1d "><div class=" container Has-text-centered "><div class=" columns "><div class=" column Is-half is-offset-one-quarter vertical-align ">vueflix='/'new vuerouter ({routes})
Above you can see the first routing component we define Intro, we route this component {path: '/', component:intro} and instantiate our route new Vuerouter ({routes}).
Note: There are several ways to define a component template through Vue. The components of the movie introduction and movie detail Page use ES6 template text to define multiple paths to the template. Anthony Gore has an article: 7 Ways to Define a Component Template in Vue.js.
We now need to inject our router into the Vue instance, which allows the entire app to route and render to our dom<router-view></router-view>.
Inject our router into the Vue instance:
New' #app ', Router:router,data () {return {moviechoices:movies} }})
Render our routing components in the DOM:
<div id= "app" ><section class= "hero is-primary Is-medium" ><router-view></router-view>< Div class= "Hero-foot" ><div class= "columns" ><div vfor = "Moviechoice in Moviechoices" class= " Column "><li class=" Movie-choice "><p class= "mobile" >{{moviechoice.subtitle}}</p></li></div></div></div></ Section></div>
We have succeeded in creating our first root path: path: '/' to show our introcomponent. As we add all of the styles, our application should look like this:
Movie components (multi-route)
We now have the app complete the main path we specified and the layout of our footer section. Let's extend the path to a movie component that shows all the information for a particular movie.
First, let's set up the navigation correctly. As mentioned earlier, the purpose of our footer setting is to allow users to navigate between movies. We will use the Router-link component of Vue's vue-router to navigate and provide the corresponding destination address.
Go back to HTML and make small edits to the footer section:
<div id= "app" ><section class= "hero is-primary Is-medium" ><router-view></router-view>< Div class= "Hero-foot" ><div class= "columns" ><div vfor = "Moviechoice in Moviechoices" class= " Column "><router-link:to=" '/${moviechoice.id} ' "tag=" Li "class=" Movie-choice "><p class= "mobile" >{{moviechoice.subtitle}}</p ></router-link></div></div></div></section></div>
We have created a '/${moviechoice.id} ' using the target URL of the ES6 template text label as the ID of the independent movie (e.g. the path of the Dark Knight Rise/the-dark-knight-rises). The tag parameter indicates that we want our router-link to be rendered as an Li while still listening for click events.
To complement our new navigation path, we need to set up a dynamic route for our movie components. Go back to where we set the path:
Const ROUTES ='/''/:id ', Component:movie}]
We've already represented with a dynamic segment: ID points to each route in the same component movie. We are now able to get different dynamic segment components by reading $route.params.id.
Now that we've set up a route for the movie component, let's quickly draft the components and make sure our routing works.
First draft of the movie component:
Const Movie = {Template: '<div><div class= ' hero-body ' ><div class= ' container has-text-centered "><div class=" columns "><div class=" column is-half is-offset-one-quarter vertical-align ">{{selectedmovie.title}}data () {return {selectedmovie:movies[this. $route. params.id ]}},watch: {$route () {this. Selectmovie ()}},methods: {Selectmovie ()} {this. Selectedmovie = movies[this. $route. params.id] }}
Here are a few things to keep in mind.
data () {return {selectedmovie:movies[this. $route. params.id]}}
The data function sets the Selectedmovie property within the component based on $route.params.id and can save the object from the global movies.
So suppose the movie chooses The Dark Knight to Rise, and this selectedmovie will be movies[the-dark-knight-rises].
Watch: {$route () {this. Selectmovie ()}},methods: {Selectmovie ()} {this. Selectedmovie = movies[this. $route. params.id]}}
We use watch to look at the path and then have any changes to the Selectmovie method of the calling component. The method selectmovie simple update Selectedmovie parameters with the selection of new movies. This must be handled when the user switches from one movie component to another (that is, the switch movie).
To test all things, we should be able to see that the route has been working:
Now that we know that our routing is working well, we will update the templates in our movie components to show all the expected information about the movie.
Const Movie ={Template: '<div class= "Hero-body": Style= "{' Background-image ': selectedmovie.largeimgsrc}" >Home</router-link><a class= "Nav-item is-active" ><span class= "tag is-rounded" >Films</span></ A><a class= "Nav-item is-active" >shows</a><a class= "Nav-item is-active" >Music</a></div><div class= "nav-right desktop" ><span class= "Nav-item" ><a class= "title" >Vueflix</a></span></div></div>link:to= "{path: '/' + $route. Params.id + '/trailer '}"class= "button Play-button" >Play<i class= "FA fa-play" ></i></router-link></div></div></div></div></ Div> ',}
We have set up a Router-link component on the homepage link in the navigation bar user directly back to the root path (part of the introduction movie).
We introduced another router-link, the play button in the movie, to create a target location for the '/' + $route. Params.id + '/trailer '. This basically expands the current path and trailer of the movie ID with/trailer, which is the navigation to our final movie trailer component.
So far, the movie components in our application should look like this:
It's amazing. Since we have built a suitable router-link to guide users from movies to movie trailers, now we need to create movie trailer components and corresponding dynamic routes.
Movie Trailer:
Const Movietrailer = {Template: '<div class= ' trailer-body "style=" background: #1e1d1d "><div class=" Has-text-centered "><div class=" columns "><div class=" column Vertical-align ">< Iframeallowfullscreenframeborder= "0"height= "376": src= "Trailerurlpath"style= " width:100%; Min-width:536px "/></div></div></div></div>",data () {return { trailerurlpath:movies[this. $route. Params.id].trailerpath} }}
We use a simple iframe to display the trailer from YouTube. We bind the src of the IFRAME to the component's properties Trailerurlpath set in the data function. The simple Trailerurlpath accesses the global movies and gets the URL based on $route.params.id appropriate movie information.
Along with dynamic routing:
Const ROUTES ='/''/:id '/:id/trailer ', Component:movietrailer}]
Our app at this moment:
We're almost done! We just need to solve a simple Add movie collection and Vueflix that is complete.
Add to Favorites
Each movie object in the movies has a Boolean value of favorite. We will use this trigger to indicate whether a movie has been added to the Favorites folder.
For visual display, we will have two visual cues:
We help us do this by building on the Favorite-shadow and Favourite-check classes we have reserved.
. favorite-Shadow {box-shadow:0 0 50px 15px rgba (251, 255, 0.25);}. Favorite-check {position:absolute;right:5px;top:5px;z-index:1; color: #fcff4c; @media (Max- width: $medium) {position:initial;display:block;}}
Now we need to apply conditional class bindings in the movie Component template and Footer section. We also need to create an event handler for the Add to Favorites button in the movie component.
Our Movie components:
Const Movie ={Template: '<div:class= "[{' Favorite-shadow ': selectedmovie.favorite}, ' Hero-body ']": Style= "{' Background-image ': selectedmovie.largeimgsrc}" >............<div class= "Links" ><router-link:to= "{path: '/' + $route. Params.id + '/trailer '}"class= "button Play-button" >Play<i class= "FA fa-play" ></i></router-link><AClass= "button Is-link Favorites-button"@click= "AddToFavorites" ><Span:class= "[{' Hide ': selectedmovie.favorite}]" >Add to</span><Span:class= "[{' Hide ':!selectedmovie.favorite}]" >Remove from</span> favorites<i class= "fa fa-plus-square-o" ></i></a></div></div></div> ",data () {...},watch: {},methods: {Selectmovie () {...},addtofavorites () {movies[ This. $route. Params.id].favorite =!movies[ This. $route. Params.id].favorite}}
The combination of the above class Favorite-shadow is determined by the Selectedmovie.favorite Boolean value and Hero-body should always be present.
We also launched the ' Add/Remove ' from the Favorites button after the original play button. The Add to Favorites button handles a simple toggle from the AddToFavorites () method when you click the favorite of a movie, the text toggles between "add" and "delete" based on whether the movie has been added or removed from the favorites (The Hide class is the Create class setting display: None), do not add there on the delete.
Similarly, we also need to introduce a conditional class binding that checks the markup in the footer:
<div id= "app" ><section class= "hero is-primary Is-medium" ><router-view></router-view>< Div class= "Hero-foot" ><div class= "columns Is-mobile" ><div v-for = "Moviechoice in Moviechoices" class= "column" ><router-link:to= "'/${moviechoice.id} '"tag= "Li"class= "Movie-choice" > <i:class= "[{' FA fa-check-circle Favorite-check ': moviechoice.favorite}]" ></i><p class=" mobile movie-title ">{{Moviechoice.subtitle}}</p ></router-link></div></div></div></section></div>
Now we should be able to add the movie to our favorites list!
Cheers!
Thank you for taking the time to look at this article. This is a common exercise for us to break the bottleneck together and learn more about the Vue.js concept, so I hope this is helpful, what have you learned?
If you have any questions/comments, I will be glad to hear it!
The original author of this article, Hassan Djirdeh, by the blogger translation, the blogger's many vue.js tutorials can also be here.
Use Vue.js to develop a front-end part of a movie app