Vue js and Vue Material

Post on 16-Apr-2017

689 views 7 download

Transcript of Vue js and Vue Material

1 / 48

Introduction - by Examples

Vue.JSEueung Mulyana

https://eueung.github.io/112016/vuejsCodeLabs | Attribution-ShareAlike CC BY-SA

Vue.JS Version: 2.1.6Vue Material Version: 0.5.1

2 / 48

Outline

Introduction

Basic Examples

vue-cli

Vue Components

3 / 48

Introduction

4 / 48

5 / 48

Vue is a progressive framework for building user interfaces.Unlike other monolithic frameworks, Vue is designed from

the ground up to be incrementally adoptable.

The core library is focused on the view layer only, and is very easy to pick up andintegrate with other libraries or existing projects. On the other hand, Vue is also

perfectly capable of powering sophisticated Single-Page Applications when used incombination with modern tooling and supporting libraries.

Ref: Vue.JS - Guide

Vue.JS

6 / 48

Vue & React

They share many similarities:

utilize a virtual DOMprovide reactive and composable view componentsmaintain focus in the core library, with concerns such as routing and globalstate management handled by companion libraries

In React, everything is Just JavaScript, which sounds verysimple and elegant - until you dig deeper. The unfortunatereality is that reinventing HTML and CSS within JavaScript,

while solving some issues of the traditional model, can alsocause pain of its own. Vue, instead, utilizes web technologies

and build on top of them. Ref: Comparison.

Deja Vue?Vue has many features that are clearlyinspired by other frameworks. This is agood thing; it's great to see newframeworks take some ideas from otherlibraries and improve on them.

In particular, you'll see Vue's templatingis very close to Angular, but itscomponents and component lifecyclemethods are closer to React.

Ref: jfranklin @SitePoint

Basic Examples

7 / 48

<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <title>Vue.JS</title>

<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic" <link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons"> <link rel="stylesheet" href="//unpkg.com/vue-material@latest/dist/vue-material.css"> <style> .main-content { padding: 16px; } .red { color:red; }</style></head>

<body>

<div id="app"> <md-toolbar> <h1 class="md-title">Learning Vue.JS</h1> </md-toolbar>

<div class="main-content"> <h1>{{ message1 }}</h1><h3 class="red">v-on:click</h3> <md-button class="md-raised md-primary" v-on:click="reverseMessage">Reverse</md-button>

<h3 class="red">v-bind:title</h3><p v-bind:title="message2">123 123 123 123 123</p> <h3 class="red">v-if</h3><p v-if="seen">v-if show-hide: Now you see me</p>

<h3 class="red">v-for</h3> <ol><li v-for="todo in todos">{{ todo.text }}</li></ol>

<h1>{{ message3 }}</h1><h3 class="red">v-model</h3> <md-input-container> <label>Enter Message</label> <md-input v-model="message3"></md-input> </md-input-container>

<h3 class="red">Component</h3> <ol> <todo-item v-for="item in groceryList" v-bind:todo="item"></todo-item> </ol>

</div></div>

<script src="//unpkg.com/vue/dist/vue.js"></script><script src="//unpkg.com/vue-material@latest"></script>

8 / 48

Example #1

9 / 48

Example #1

10 / 48

Example #1

11 / 48

Example #1Interaction via Console

<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <title>Vue.JS</title>

<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic" <link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons"> <link rel="stylesheet" href="//unpkg.com/vue-material@latest/dist/vue-material.css"> <style> .main-content { padding: 16px; } .red { color:red;} ul {padding-left:0;} li {list-style:none; line-height: 40px;} .md-button {margin-left:0;} </style></head>

<body>

<div id="app"> <md-toolbar> <h1 class="md-title">Learning Vue.JS</h1> </md-toolbar>

<div class="main-content"> <md-input-container> <label>Enter Todo</label> <md-input v-model="newTodo"></md-input> </md-input-container> <md-button class="md-raised md-primary" v-on:click="addTodo">Add Todo</md-button>

<ul> <li v-for="(todo, index) in todos"> <md-button class="md-icon-button md-warn" v-on:click="removeTodo(index)"><md-icon>remove_circle_outline {{ todo.text }} </li> </ul>

</div></div>

<script src="//unpkg.com/vue/dist/vue.js"></script><script src="//unpkg.com/vue-material@latest"></script>

<script type="text/javascript"> Vue.use(VueMaterial)

12 / 48

Example #2a

Example #2a

13 / 48

<head> <meta charset="utf-8"> <title>Vue.JS</title>

<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic" <link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons"> <link rel="stylesheet" href="//unpkg.com/vue-material@latest/dist/vue-material.css"> <style> .main-content { padding: 16px; } .red { color:red;} ul {padding-left:0;} li {list-style:none; line-height: 40px;} .md-button {margin-left:0;} </style></head>

<body>

<div id="app"> <md-toolbar> <h1 class="md-title">Learning Vue.JS</h1> </md-toolbar>

<div class="main-content"> <md-input-container> <label>Enter Todo</label> <md-input v-model="newTodoText" placeholder="Add a todo"></md-input> </md-input-container> <md-button class="md-raised md-primary" v-on:click="addNewTodo">Add Todo</md-button>

<ul> <li is="todo-item" v-for="(todo, index) in todos" v-bind:title="todo" v-on:remove="todos.splice(index, 1)"> </li> </ul>

</div></div>

<script src="//unpkg.com/vue/dist/vue.js"></script><script src="//unpkg.com/vue-material@latest"></script>

<script type="text/javascript">

Vue.use(VueMaterial)

14 / 48

Example #2bVue ComponentEvent

Example #2b

15 / 48

vue-cli

16 / 48

17 / 48

Install & Scaffold

$ sudo npm install -g vue-cli

$ vue init webpack-simple myproj

This will install Vue 2.x version of template.

For Vue 1.x use: vue init webpack-simple#1.0 myproj

? Project name myproj? Project description A Vue.js project? Author EM

vue-cli . Generated "myproj".

To get started:

cd myproj npm install npm run dev

myproj$ tree.|-- index.html|-- package.json|-- README.md|-- src| |-- App.vue| |-- assets| | |-- logo.png| |-- main.js|-- webpack.config.js

2 directories, 7 files

18 / 48

package.json

myproj$ cat package.json { "name": "myproj", "description": "A Vue.js project", "version": "1.0.0", "author": "EM", "private": true, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --inline --hot -host 0.0.0.0" "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { "vue": "̂2.1.0" }, "devDependencies": { "babel-core": "̂6.0.0", "babel-loader": "̂6.0.0", "babel-preset-es2015": "̂6.0.0", "cross-env": "̂3.0.0", "css-loader": "̂0.25.0", "file-loader": "̂0.9.0", "vue-loader": "̂10.0.0", "vue-template-compiler": "̂2.1.0", "webpack": "̂2.1.0-beta.25", "webpack-dev-server": "̂2.1.0-beta.9" }}

19 / 48

Install & Run

myproj$ npm installmyproj$ npm run dev> myproj@1.0.0 dev /home/em/vuedir/myproj> cross-env NODE_ENV=development webpack-dev-server --open --inline --hot --host 0.0.0.0

Project is running at http://0.0.0.0:8080/webpack output is served from /dist/404s will fallback to /index.html

myproj$ npm run build

vue init webpack-simple20 / 48

<html lang="en"> <head> <meta charset="utf-8"> <title>myproj</title> </head> <body> <div id="app"></div> <script src="/dist/build.js"></script> </body></html>

# App.vue<template> <div id="app"> <img src="./assets/logo.png"> <h1>{{ msg }}</h1> <h2>Essential Links</h2> <ul> <li><a href="https://vuejs.org" target="_blank">Core Docs</a></li> <li>...</li> </ul> <h2>Ecosystem</h2> <ul> <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li> <li>...</li> </ul> </div></template>

<script>export default { name: 'app', data () { return { msg: 'Welcome to Your Vue.js App' } }}</script>

<style>

#app { font-family: 'Avenir', Helvetica, Arial, sans-serif; 21 / 48

webpack-simpleindex.htmlApp.vuemain.js

22 / 48

Example #2aRecycled

$ npm install$ npm install --save vue-material

$ tree .|-- dist| |-- build.js|-- index.html|-- package.json|-- README.md|-- src| |-- App.vue| |-- css| | |-- app.css| |-- main.js|-- webpack.config.js

$ npm run build$ npm run dev

23 / 48

package.jsonwebpack.config.js

$ cat package.json { ... "dependencies": { "vue": "̂2.1.0", "vue-material": "̂0.5.1" }, ...}

$ cat webpack.config.js module: { rules: [ ... { test: /\.css$/, loader: 'vue-style-loader!css-loader' }, ... ], } ...

<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic" <link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons">

<title>myproj</title> </head> <body> <div id="app"></div> <script src="/dist/build.js"></script> </body></html>

# -------------------

.main-content { padding: 16px; } .red { color:red;} ul {padding-left:0;} li {list-style:none; line-height: 40px;} .md-button {margin-left:0;}

24 / 48

Example #2aindex.htmlsrc/css/app.css

import Vue from 'vue'import App from './App.vue'import VueMaterial from 'vue-material'import 'vue-material/dist/vue-material.css'import './css/app.css'

Vue.use(VueMaterial)

new Vue({ el: '#app', render: h => h(App)})

/* --------------------------- */

<template><div id="app"> <md-toolbar> <h1 class="md-title">Learning Vue.JS</h1> </md-toolbar>

<div class="main-content"> <md-input-container> <label>Enter Todo</label> <md-input v-model="newTodo"></md-input> </md-input-container> <md-button class="md-raised md-primary" v-on:click="addTodo">Add Todo</md-button>

<ul> <li v-for="(todo, index) in todos"> <md-button class="md-icon-button md-warn" v-on:click="removeTodo(index)"><md-icon>remove_circle_outline</md-icon></md-button> {{ todo.text }} </li> </ul></div></div></template>

<script>export default { name: 'app', data () { return { newTodo: '', todos: [ { text: 'Add some todos' } ] } 25 / 48

Example #2amain.jssrc/App.vue

Example #2a (webpack)26 / 48

Vue Components

27 / 48

28 / 48

Example #3

Example #3aBased on an Article @SitePoint by Jack FranklinComponents are re-organized to a single index.vue

Example #3bExample #3a + Vue Material

29 / 48

Example #3aStructure

$ tree.|-- build| |-- main.js|-- index.html|-- package.json|-- src| |-- App| | |-- index.vue| |-- bus.js| |-- GithubInput| | |-- index.vue| |-- GithubOutput| | |-- index.vue| |-- GithubUserData| | |-- index.vue| |-- main.js|-- webpack.config.js

6 directories, 10 files

{ "name": "vue2-intro-code", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "live-server", "build": "webpack --watch" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-core": "6.18.2", "babel-loader": "6.2.7", "babel-preset-es2015": "6.18.0", "css-loader": "0.25.0", "live-server": "1.1.0", "vue": "2.1.6", "vue-loader": "10.0.0", "vue-template-compiler": "̂2.1.0", "webpack": "1.13.3" }}

/* --------------------------- */

module.exports = { entry: './src/main', output: { path: './build', filename: 'main.js', }, module: { loaders: [ { test: /\.vue$/, loader: 'vue', }, { test: /\.js$/, loader: 'babel', exclude: /node_modules/, 30 / 48

Example #3apackage.jsonwebpack.con�g.jsindex.html

31 / 48

import Vue from 'vue'

import AppComponent from './App/index.vue'

const vm = new Vue({ el: '#app', components: { app: AppComponent, }, render: h => h('app'),})

/* --------------------------- */

import Vue from 'vue'

const bus = new Vue()

export default bus

Example #3asrc/main.jssrc/bus.js

<template><div> <p>Enter your username to get some Github stats!</p> <github-input></github-input> <github-output></github-output></div></template>

<script>import GithubInput from '../GithubInput/index.vue'import GithubOutput from '../GithubOutput/index.vue'

export default { name: 'App', components: { 'github-input': GithubInput, 'github-output': GithubOutput, }, data() { return {} },}</script>

<style scoped>p { color: red;}</style>

32 / 48

Example #3asrc/App/index.vue

<template><form v-on:submit.prevent="onSubmit"> <input type="text" v-model="username" placeholder="Enter a github username here" /> <button type="submit">Go!</button></form></template>

<script>import bus from '../bus'

export default { name: 'GithubInput', methods: { onSubmit(event) { if (this.username && this.username !== '') { bus.$emit('new-username', this.username) } } }, data() { return { username: '', } }}</script>

33 / 48

Example #3a

src/GithubInput/index.vue

<template><div> <p v-if="currentUsername == null"> Enter a username above to see their Github data </p> <p v-else> Below are the results for {{ currentUsername }}: <github-user-data :data="githubData[currentUsername]"></github-user-data> </p></div></template>

<script>import bus from '../bus'import Vue from 'vue'import GithubUserData from '../GithubUserData/index.vue'

export default { name: 'GithubOutput', components: { 'github-user-data': GithubUserData, }, created() { bus.$on('new-username', this.onUsernameChange) }, destroyed() { bus.$off('new-username', this.onUsernameChange) }, methods: { onUsernameChange(name) { this.currentUsername = name this.fetchGithubData(name) }, fetchGithubData(name) { if (this.githubData.hasOwnProperty(name)) return

const url = ̀https://api.github.com/users/${name}̀ fetch(url).then(r => r.json()).then(data => { Vue.set(this.githubData, name, data) console.log(JSON.stringify(this.githubData)) }) } }, 34 / 48

Example #3a

src/GithubOutput/index.vue

35 / 48

<template><div v-if="data"> <h4>{{ data.name }}</h4> <p>{{ data.company }}</p> <p>Number of repos: {{ data.public_repos }}</div></template>

<script>export default { name: 'GithubUserData', props: ['data'], data() { return {} }}</script>

Example #3a

src/GithubUserData/index.vue

Example #3a36 / 48

Example #3a37 / 48

38 / 48

Example #3bStructure

$ tree.|-- dist| |-- build.js| |-- build.js.map|-- index.html|-- package.json|-- src| |-- App| | |-- index.vue| |-- bus.js| |-- css| | |-- app.css| |-- GithubInput| | |-- index.vue| |-- GithubOutput| | |-- index.vue| |-- GithubUserData| | |-- index.vue| |-- main.js|-- webpack.config.js

7 directories, 12 files

{ "name": "myproj", "description": "A Vue.js project", "version": "1.0.0", "author": "EM", "private": true, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --inline --hot --host 0.0.0.0" "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" }, "dependencies": { "vue": "̂2.1.0", "vue-material": "̂0.5.1" }, "devDependencies": { "babel-core": "̂6.0.0", "babel-loader": "̂6.0.0", "babel-preset-es2015": "̂6.0.0", "cross-env": "̂3.0.0", "css-loader": "̂0.25.0", "file-loader": "̂0.9.0", "vue-loader": "̂10.0.0", "vue-template-compiler": "̂2.1.0", "webpack": "̂2.1.0-beta.25", "webpack-dev-server": "̂2.1.0-beta.9" }}

39 / 48

Example #3bpackage.json

var path = require('path')var webpack = require('webpack')

module.exports = { entry: './src/main.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist/', filename: 'build.js' }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { // Since sass-loader (weirdly) has SCSS as its default parse mode, we map // the "scss" and "sass" values for the lang attribute to the right configs here. // other preprocessors should work out of the box, no loader config like this nessessary. 'scss': 'vue-style-loader!css-loader!sass-loader', 'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax' } // other vue-loader options go here } }, { test: /\.css$/, loader: 'vue-style-loader!css-loader' }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]' }

40 / 48

Example #3bwebpack.con�g.js

<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic" <link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons">

<title>myproj</title> </head> <body> <div id="app"></div> <script src="/dist/build.js"></script> </body></html>

/* --------------------------- */import Vue from 'vue'

import AppComponent from './App/index.vue'import VueMaterial from 'vue-material'import 'vue-material/dist/vue-material.css'import './css/app.css'

Vue.use(VueMaterial)

const vm = new Vue({ el: '#app', components: { app: AppComponent, }, render: h => h('app'),})

/* --------------------------- */.main-content { padding: 16px; } .red { color:red;} ul {padding-left:0;} li {list-style:none; line-height: 40px;} .md-button {margin-left:0;}

41 / 48

Example #3bindex.htmlsrc/main.jssrc/css/app.css

<template><div id="app"> <md-toolbar> <h1 class="md-title">Learning Vue.JS</h1> </md-toolbar> <div class="main-content">

<p>Enter your username to get some Github stats!</p> <github-input></github-input> <github-output></github-output>

</div></div></template>

<script>import GithubInput from '../GithubInput/index.vue'import GithubOutput from '../GithubOutput/index.vue'

export default { name: 'App', components: { 'github-input': GithubInput, 'github-output': GithubOutput, }, data() { return {} },}</script>

<style scoped>p { color: red;}</style>

42 / 48

Example #3bsrc/App/index.vue

<template><div> <md-input-container> <label>Github User</label> <md-input v-model="username" placeholder="Enter a github username here"></md-input> </md-input-container> <md-button class="md-raised md-primary" v-on:click="onSubmit">Go!</md-button></div></template>

<script>import bus from '../bus'

export default { name: 'GithubInput', methods: { onSubmit(event) { if (this.username && this.username !== '') { bus.$emit('new-username', this.username) } } }, data() { return { username: '', } }}</script>

43 / 48

Example #3b

src/GithubInput/index.vue

Example #3b44 / 48

Example #3b45 / 48

Refs

46 / 48

Refs1. vuejs.org2. vuejs/vue: Simple yet powerful library for building modern web interfaces.3. Comparison with Other Frameworks - vue.js4. Introduction - Vue Material5. Getting up and Running with the Vue.js 2.0 Framework6. jackfranklin/vue2-demo-proj

47 / 48

48 / 48

ENDEueung Mulyana

https://eueung.github.io/112016/vuejsCodeLabs | Attribution-ShareAlike CC BY-SA