Vue.js 2.0 In 60 Minutes
Link: https://www.youtube.com/watch?v=z6hQqgvGI4Y
Recommended watching:
- Vue CLI and .vue files - how to install Vue CLI and use the webpack template
- Components and .vue files - how to create components using single file vue technique
- How to Install Webpack, Setup a Config File, and Minify JavaScript - how webpack work
- Webpack Loaders for CSS, SCSS, ES6, and JSHint - learn to use webpack loader (eg. bundle together css)
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 #
- Vue vs React
- similar
- works with UI only
- working with virtual dom
- component-based
- external library for routing
- Vue vs Angular 2
- not UI library
- a complete framework
- more powerful
- perfomance, Vue because lightweight
- Vue vs Ember
- older
- Vue vs Knockout
- MVVM
- Vue is not MVVM but works similar way
- lack of lifecycle
- Vue vs Polymer vs Riot
What Vue Offers #
- Reactive interfaces
- click here, react somewhere
- Declarative rendering
- variables for data binding
- Components & nesting
- Event handling
- Data binding
- Computed properties
- Directives
- CSS transitions & animations
- Template logic
- if statements, for loops in template
- 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 }
]
}
- If statement
<p v-if="show">This is shown</p>
<p v-else>This is not</p>
- Show, is set to true in the data
<p v-show="show">This is shown</p>
-
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 #
- vue-router – official router
- vue-resource – networking library
- vue-async-data – async data loading
- vue-validator – form validation plugin
- vue-devtools – chrome devtools extension
- vue-touch – touch gestures using Hammer.js
Starting a project #
-
Install it using NPM
$ npm install -g vue-cli
-
Create a project
$ vue init webpack vueapp
Will ask some questions. Enter to agree. -
Install dependencies
$ cd vueapp
$ npm install
-
Open using text editor
-
Run web server
$ npm run dev
-
Open in browser
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)
- in
- It should auto reload in the browser
- Create a new component in
components
folder calledTest.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
ifshowName
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
andlastName
together into a String - call
computed
inside script tag and create a new function calledfullName
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 withmsg
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 adeleteUser(user)
method which takes auser
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 usingcreated
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
andemail
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 theroutes
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 componentrouter-view
is the view wanted to display based on the component chosen