Getting Started
- Comparison with React & Angular
- Extremely lean & small
- great runtime performance
- feature-rich, very extendable
- Vue instance is the core of a VueJs application
Using VueJS to Interactwith the DOM
- The {{ }} syntax is called “interpolation” or “String interpolation”,
- inside value should be something that could be converted to a string
- cannot be used in html element attribute, instead use v-bind directive
- Virtual DOM: VueJs creates a template based on html code, stores it internally and uses this template to create the real html code, which is finally rendered as the DOM
- Directive:
- an instruction in code
- v-once: the content inside this element will be only rendered once, won’t be updated later on when the property inside is changed
- v-html:
- by default, vuejs only renders text, no html elements to prevent cross-site scripting
- allow to pass in and render html code
- v-on:
- listen an event to receive info from template
- binding function has direct access to the event object
- pass both the customized variable and event object
- functionName(varName, $event);
- event modifier:
- .stop
- .prevent
- .capture
- .once
- .passive
- key modifier:
- .enter
- .tab
- .delete (both “Delete” and “Backspace” keys)
- .space
- .up
- .down
- .left
- .right
Event modifier:
<!-- the click event's propagation will be stopped -->
<a v-on:click.stop="doThis"></a>
<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- modifiers can be chained -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- just the modifier -->
<form v-on:submit.prevent></form>
<!-- use capture mode when adding the event listener -->
<!-- i.e. an event targeting an inner element is handled here before being handled by that element -->
<div v-on:click.capture="doThis">...</div>
<!-- only trigger handler if event.target is the element itself -->
<!-- i.e. not from a child element -->
<div v-on:click.self="doThat">...</div>
New in 2.1.4+
<!-- the click event will be triggered at most once -->
<a v-on:click.once="doThis"></a>
New in 2.3.0+
<!-- the scroll event's default behavior (scrolling) will happen -->
<!-- immediately, instead of waiting for `onScroll` to complete -->
<!-- in case it contains `event.preventDefault()`-->
<div v-on:scroll.passive="onScroll">...</div>
https://vuejs.org/v2/guide/events.html#Event-Modifiers
Key modifier:
<!-- only call `vm.submit()` when the `key` is `Enter` -->
<input v-on:keyup.enter="submit">
<!-- kebab-case -->
<input v-on:keyup.page-down="onPageDown">
https://vuejs.org/v2/guide/events.html#Key-Modifiers
- Two-way data binding:
- v-model=”propertyName”
- Computed properties:
- data properties are not reactive
- Method 1: move the data to methods
- problem: will be executed each time re-rendering the page
- Method 2: computed property
- would not run unless the related value is changed
- problem: always run synchronously
- watch properties:
- the same with one of the data properties
- get executed whenever the data property changed
- Shorthands:
- v-on: = @
- v-bind: = :
- Dynamic Styling
- :class ->
- an object which has the class name (‘is-active’ or isActive) as key, and a Boolean as value
- a class name or an array of class names
- mixture: an array contains an object
- :style ->
- an object which has the style property name as key, style value as value
- an array of objects
- :class ->
Using Conditionals and Rendering Lists
- v-if
- attach or detach the element from DOM, not only hide it
- make use of <template></template> to wrap multiple elements
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
// from version 2.1.0+
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
- v-show
- the element stays, but hidden with CSS style
- Rendering Lists with v-for
- loop over array
- loop over object
- loop over number, start from 1
// For array with index
<ul id="example">
<li v-for="(item, index) in items">
{{ index }} - {{ item.message }}
</li>
</ul>
// For object with value
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
// For object with value and key (and index)
<ul id="v-for-object" class="demo">
<li v-for="(value, key(, index)) in object">
{{ value }}
</li>
</ul>
// For number, start from 1
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
result: 1 2 3 4 5 6 7 8 9 10
Understanding the VueJS Instance
- It’s possible to control multiple Vue instances on one page
- It’s possible to access the vue instance from outside, when assign it to a variable
- When using the $refs to access an element, it directly manipulate the DOM element, not go through VueJs Virtual DOM, it’s better to make use of it to get value, instead of update value
Development Workflow with Webpack and Vue CLI
- Vue CLI
- fetch different templates
An Introduction to Components
- Components vs instance
- Components are reusable while instance is not
- data is a property to instance while data is a function returns an object to a component
- Components can be registered both globally and locally
- Component allows only one root element
Communication between components
- props:
- from Parent to Child
- can be used the same way with data
- assign a type and ‘required’ property to perform validation, or default value
- ! object and array are passing by reference, the change in the children element would also change the value in parent element
- custom event:
- from Child to Parent
- in child element, emit the event: $emit(eventName, parameter)
- in parent element, listen to the event: @eventName(parameter
- Alternative to custom event:
- callback function: pass the function in parent element as a prop to child element
- communication between sibling components
- childA -> custom event -> parent -> update childB
- callback function
- a central class (Event Bus) to manage the state of a property across multiple components:
- create eventBus instance on root before initial the main vue instance
- emit event on eventBus instance
- catch the event in the target child element on eventBus in created() life hook
- ! the emit function could be in the child element or in the eventBus instance
Advance Component Usage
- Slot
- put in the child component where want to receive data
- when rendering, the slot will be replaced by the content passed in from parent
- styling and data are handled on the parent component
- multiple slots (named slots)
- unnamed slot is the default slot
- default slot will be displayed when no content passed in
// Child component define slot with name
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
// Parent component pass in the content
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default> // can be omitted
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template> // can be omitted
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
- Dynamic component
- switch between components
- the component is actually created and destroyed
- wrap in <keep-alive> to preserve the state
- when switching between components within <keep-alive> tags, instead of destroyed: new lifecycle hooks are activated() and deactivated()
<component :is="currentTabComponent"></component>
Handling User Input with Forms
- Input modifiers
- .lazy: not update instantly, synced after “change” instead of “input”
- .trim
- .number: automatically typecast as a Number
- <textarea>
- interpolation doesn’t work
- use v-model, need to pay attention to the line break style
- checkbox
- save data in array, bind the array to the input elements
- radio button
- v-model bind the group of radio buttons to the same property/data
- dropdown <select> & <option>
- v-for to populate <option> with data
- when no v-model binded, :selected=”condition”
- v-model = :value + @input
Directives
- v-directiveName: tiny command in html code
- register the directive globally:
// Register a global custom directive called `v-focus`
Vue.directive('focus', {
// When the bound element is inserted into the DOM...
inserted: function (el) {
// Focus the element
el.focus()
}
})
- configuration for a directive: five hooks
bind: called only once, when the directive is first bound to the element. This is where you can do one-time setup work.inserted: called when the bound element has been inserted into its parent node (this only guarantees parent node presence, not necessarily in-document).update: called after the containing component’s VNode has updated, but possibly before its children have updated. The directive’s value may or may not have changed, but you can skip unnecessary updates by comparing the binding’s current and old values (see below on hook arguments).componentUpdated: called after the containing component’s VNode and the VNodes of its children have updated.unbind: called only once, when the directive is unbound from the element.
Filters & Mixins
- Filter is not so performant, instead use computed property
// HTML
<!-- in mustaches -->
{{ message | capitalize }}
<!-- in v-bind -->
<div v-bind:id="rawId | formatId"></div>
// JS
// locally
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
// globally
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// ...
})
- Mixins
- not shared but replicated.
Vuex
Central State