Vue JS

Vue.js 2.0 In 60 Minutes
Link: https://www.youtube.com/watch?v=z6hQqgvGI4Y

Recommended watching:

What is Vue JS #

  • Progressive JS framework focuses on building UI
  • works in “view layer”
    • it doesn’t care about model or db
  • easily integrate to existing project
  • powering advanced SPA

Vue vs other frameworks #

  1. Vue vs React
    • similar
    • works with UI only
    • working with virtual dom
    • component-based
    • external library for routing
  2. Vue vs Angular 2
    • not UI library
    • a complete framework
    • more powerful
    • perfomance, Vue because lightweight
  3. Vue vs Ember
    • older
  4. Vue vs Knockout
    • MVVM
    • Vue is not MVVM but works similar way
    • lack of lifecycle
  5. Vue vs Polymer vs Riot

What Vue Offers #

  1. Reactive interfaces
    • click here, react somewhere
  2. Declarative rendering
    • variables for data binding
  3. Components & nesting
  4. Event handling
  5. Data binding
  6. Computed properties
  7. Directives
  8. CSS transitions & animations
  9. Template logic
    • if statements, for loops in template
  10. Custom filters
    • create filter to add to variables

Installing #

  • include in <script> tag (not recommended for production)
  • install using NPM
  • use Vue-cli tool w/ webpack (recommended)
  • install using Bower client package manager

Vue CLI Tool #

Commands:

$ npm install -g vue-cli        ## install vue
$ vue init webpack APP_NAME ## create project with webpack template
$ cd APP_NAME
$ npm install ## install dependencies
$ npm run dev ## run dev server
$ npm run build ## build app to production

Code example #

Rendering data to the DOM & using interpolation

<div id="app">

</div>

Binding app in the DOM with Vue component

var app = new Vue({
el: "#app",
data: {
msg: "Hello world"
}
});

Interpolation - msg is the data we are sending to the view

Directives #

  • Special attr with the v- prefix that does something to the DOM
  • Reactively applies side effects to the DOM when something changes
<element v-directiveid="[argument:] expression [|filters]">
</element>

Simple directives #

Basic interpolation

<span></span>

Using v-text directive

<span v-text="msg"></span>

Parses html

<span v-html="msg"></span>

One time interpolation. Only gonna output once, if it changes, it will not be changed.

<span v-once></span>

Conditional & Loops #

Data example

data: {
show: true,
users: [
{ name: 'Bob' },
{ name: 'Kathy }
]
}
  1. If statement
<p v-if="show">This is shown</p>
<p v-else>This is not</p>
  1. Show, is set to true in the data
<p v-show="show">This is shown</p>
  1. For loop

    Loop through the users array

<li v-for="user in users"></li>

Class & style binding #

data: {
isActive: true,
activeColor: 'red'
}

Applies class active if isActive is true, otherwise it don’t

<div v-bind:class="{active: isActive}"></div>

Applies color char as style attr

<div v-bind:style="{color: activeColor}"></div>

Components #

  • Provide organization & encapsulation
  • Reusable code
  • Can be separated into .vue files
// Register
Vue.component('my-component', {
Template: 'this is my component'
});

Use is as a custom DOM

<div id="app">
<my-component></my-component>
</div>

Additional tools & plugins #

  1. vue-router – official router
  2. vue-resource – networking library
  3. vue-async-data – async data loading
  4. vue-validator – form validation plugin
  5. vue-devtools – chrome devtools extension
  6. vue-touch – touch gestures using Hammer.js

Starting a project #

  1. Install it using NPM
    $ npm install -g vue-cli

  2. Create a project
    $ vue init webpack vueapp
    Will ask some questions. Enter to agree.

  3. Install dependencies

$ cd vueapp
$ npm install
  1. Open using text editor

  2. Run web server
    $ npm run dev

  3. Open in browser

http://localhost:8080

Note: if port 8080 is being used, change a line in build/dev-server.js from

var port = process.env.PORT || config.dev.port

to

var port = 8000

Writing own code (Basic stuff) #

  • Remove any Hello related components
    • in src/components
    • in src/App.vue file (get rid of the logo as well)
  • It should auto reload in the browser
  • Create a new component in components folder called Test.vue
<template>
<div class="test">
<h1>Test</h1>
</div>
</template>

<script>
export default {
name: 'test'
}
</script>

<style scoped>
</style>
  • Add Test.vue into App.vue
  • In App.vue, under <script> section, add our Test component
<script>
import Test from './components/Test'

export default {
name: 'app',
components: {
Test
}
}
</script>
  • also in the <template> section
<template>
<div id="app">
<test></test>
</div>
</template>
  • Working in Test component, replace Test text in H1 tag with Vue JS to demonstrate interpolation
<template>
<div class="test">
<h1>Vue JS</h1>
</div>
</template>
  • in the script section, create a new data which returns a String as the title above
<script>
export default {
name: 'test',
data () {
return {
title: 'Hello world'
}
}
}
</script>

Adding an object data into the function is simply like so #

data () {
return {
title: 'Hello world',
user: {
firstName: 'John',
lastName: 'Joe'
}
}
}
  • To display the new data into our view
<div class="test">
<h1>Vue JS</h1>
<p></p> <!-- Interpolation -->
<p></p>
<p v-text="user.firstName"></p> <!-- Directive -->
</div>

To inject a HTML inside our data model, do it like so, #

title: '<h1>Hello world</h1>',
  • To parse the HTML it in the view
<span v-html="title"></span>

To demo a conditional, add a boolean into our data model #

{
title: 'Hello world',
user: {
firstName: 'John',
lastName: 'Joe'
},
showName: true
}
  • To display user.lastName if showName is true, simply
<p v-if="showName"></p> <!-- Conditional --> 
<p v-else="showName">Nobody</p> <!-- else if above is false, "Nobody" will be shown-->

To demo a for loop, create an array into our data model #

items: [
    { title: 'item1' },
    { title: 'item2' },
    { title: 'item3' },
    { title: 'item4' },
]
  • To display it in a list
<ul>
<li v-for="item in items"></li> <!-- looping items array -->
</ul>

Reacting with other elements in a template #

  • we already have an interpolation annotation called Vue JS
  • we wanted to make this annotation react with an input field from a user
<input type="text" v-model="title"> <!-- reacting to "title" annotation above (in H1 tag) -->

Event handling #

  • create a button with a directive v-on:click. This will implement a click listener to the button.
<button v-on:click="greet">Say greeting</button>
  • write a new custom function in the script tag called greet that will do something when user clicks the button
methods: {
greet: function() {
alert("Hello");
}
}
  • Holy shit, this thing even takes parameter!
<button v-on:click="greet('hello world')">Say greeting</button> <!-- there is a parameter there -->
  • also change the function to take a parameter from the view
methods: {
greet: function(greeting) {
alert(greeting);
}
}
  • another demo on event handling - onKeyUp just like in Android :^)
<input type="text" v-on:keyup="pressKey"><br/> 
pressKey: function(e) {
console.log(e.target.value); // this will capture whichever key is pressed and print it in console
}
  • when a user hit Enter key, we want to get the value from the field, use v-on:keyup.enter directive
  • of course there are other keys as well. rtfm
<input type="text" v-on:keyup="pressKey" v-on:keyup.enter="enterHit"><br/> 
enterHit: function(e) {
console.log("You hit enter: " + e.target.value);
}

Computed properties #

  • when you want to access other value from the model and compute it to some other values
  • for example, you want to concatenate firstName and lastName together into a String
  • call computed inside script tag and create a new function called fullName
computed: {
fullName: function() {
return this.user.firstName + ' ' + this.user.lastName; // calling from User model
}
}
  • The input field is to show you how reactive this thing is, even with computed properties!
<label>First name: </label><input type="text" v-model="user.firstName"><br/>
<label>Last name: </label><input type="text" v-model="user.lastName"><br/>
<h3></h3>

Component properties #

  • how about passing a value from App.vue file itself (not the view)
  • Hint: it’s in the <template> tag with msg directive
<template>
<div id="app">
<test msg="Hello"></test> <!-- THIS -->
</div>
</template>
  • we have to add a new data called props inside our script
<script>
export default {
name: 'test',
props: {
msg: {
type: String,
default: 'Foobar'
}
},
...

Writing own code (medium level) #

We want to create a CRUD stuff

Input user name and save it

  • Create a new component called Users.vue
  • Copy and paste what we have already got in Test.vue but leave the boilerplate and change any Test related stuff to Users
<template>
<div class="users">

</div>
</template>

<script>
export default {
name: 'users',
data () {
return {
}
},
methods: {

}
}
</script>

<style scoped>
</style>
  • Also need to modify App.vue to import our new Users component
<template>
<div id="app">
<!-- <test msg="Hello"></test> -->
<users></users>
</div>
</template>

<script>
import Test from './components/Test'
import Users from './components/Users'

export default {
name: 'app',
components: {
Test, Users
}
}
</script>
  • In Users.vue, create a form field for a name and an email
  • Form will take v-on:submit directive as we are submitting this form to our script
  • Input should have a v-model directive as we are creating a new object of users to be used later on
  • Also create a list bullet, just to display some users
<form v-on:submit="addUser">
<input type="text" v-model="newUser.name" placeholder="Enter name"><br/>
<input type="text" v-model="newUser.email" placeholder="Enter email"><br/>
<input type="submit" value="Submit">
</form>

<ul>
<li v-for="user in users">
:
</li>
</ul>
  • onSubmit we will be creating a function called addUser
methods: {
addUser: function(e) {
this.users.push({
name: this.newUser.name, // push a new entry to users array
email: this.newUser.email,
contacted: false
})
e.preventDefault(); // prevent flicking
}
}
  • We also need to initialize the newUser object in the *data section
data () {
return {
newUser: {}, // initialize empty object
users: [ // this is just an initial data
{
name: 'John Doe',
email: 'john@doe.com',
contacted: false
},
{
name: 'Sam Doe',
email: 'Sam@doe.com',
contacted: false
}
]
}
},
  • To delete a user, let’s create a button that will delete it
  • we are gonna use v-on:click directive with a deleteUser(user) method which takes a user object as parameter
 <button v-on:click="deleteUser(user)">X</button>
  • now let’s create the function in the script
deleteUser: function(user) {
this.users.splice(this.users.indexOf(user), 1);
}

Vue resource (networking) #

  • install it via npm

$ npm install vue-resource --save

  • run the server

$ npm run dev

  • import vue-resource into main.js
import Vue from 'vue'
import VueResource from 'vue-resource'
import App from './App'

Vue.use(VueResource) // middleware for vue-resource

...

Using the GET method #

  • as an example, we use “https://jsonplaceholder.typicode.com/users” for the API endpoint
  • use this endpoint in Users.vue script using created function
  • to use the GET method, we need to use $http built-in vue-resource
created: function() {
this.$http.get('https://jsonplaceholder.typicode.com/users') // it's gonna return a promise
.then(function(response) {
console.log(response.data);
});
}
  • we’re gonna replace our Users data with the API response
  • remove everything in users array, let it be empty
  • the API response has name and email in the body so it will replace it once it’s loaded
  • to replace it with the response, simply pass the response data into our users array
.then(function(response) {
this.users = response.data;
});

Vue Router #

Here comes the pretty URLs!

This is for routing pages/components (eg. http://localhost/user)

  • install it via npm

$ npm install vue-router --save

  • run the server again

$ npm run dev

  • import vue-resource into main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import VueResource from 'vue-resource'
import App from './App'

Vue.use(VueResource) // middleware for vue-resource
Vue.use(VueRouter) // middleware for vue-router

...

Creating router #

so we are gonna make Users becoming our homepage, so the URL should be at the root (eg. "/")

and Test is gonna be another page (eg. "/test");

  • create a constant variable which holds the Router object
  • define the mode (rtfm), and the routes we want
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [
{ path: '/', component: Users }, // Users for the homepage
{ path: '/test', component: Test }, // /test will load Test component
]
})
  • in the Vue() object at the bottom, we have to modify it so that it follows a new template (one of the way to define a template)
new Vue({
router,
// el: '#app', // we don't need this as we are using a template below
template: `
<div id="app">
<ul>
<li><router-link to="/">Users</router-link></li>
<li><router-link to="/test">Test</router-link></li>
</ul>
<router-view></router-view>
</div>
`
,
// components: { App } // we don't need this App.vue anymore as we are having multiple pages with routing capability now
}).$mount('#app') // we target everything to the `app` id in the template
  • router-link is a hyperlink to the particular component
  • router-view is the view wanted to display based on the component chosen