Direct <script> include - at the end of <body>, vue.js or vue.min.js (production)
CLI (with webpack, test, etc.)
# install vue-cli
$ npm install --global vue-cli
# create a new project using the "webpack" template
$ vue init webpack my-project
# install dependencies and go!
$ cd my-project
$ npm install
$ npm run dev
progressive - start from view -> single page application
multiple Vue in one page
partially inspired by MVVM pattern
view <=> viewmodel -> <- Model
core
render data in JS model (app) to {{}}, attribute etc template (automatically, linked)
no need to touch DOM - all handled by linking
bind not only data but also structure (loop, see/not) & apply transition effect
input
v-on to attach listeners
v-model to make two-way binding
composition
a component is a Vue instance with pre-defined options
define a composition Vue.component('tag-name', {...
use a component <tag-name>...</tag-name>
syntax - after custom element spec and implement Slot API and "is" with more
install
Vue Devtools - browser tool for better debug
direct download and include
CDN - browser download from cdn.jsdelivr.net
NPM
vue-cli
Different builds
full = compiler + runtime
compiler - for compiling template into JS
runtime
UMD - used directly in browser via <script>
CommonJS - for use with older bundlers
ES module - for modern bundlers like webpack2 / rollup
new vm = Vue(options_object)
vm, conventionally for "view model"
options_object : https://vuejs.org/v2/api/#Options-Data
data : data_object
all properties, at the moment of instance creation, reactive - linked, will re-render
vm=new Vue({ data:data}); vm.a is data.a (linked)
Object.freeze(data) - disable link
$ properties
vm.$data === data (the data object)
vm.$el === document.getElementById('the_el_property')
vm.$watch('some_data', function(newValue, oldValue) {...});
life cycle hooks (properties in option object)
called with "this" being the Vue instance
don't use => functions on options property or callback
because => functions are bound to parent context
life cycle
roughly beforeCreate -> create -> beforeMount -> mounted -> (beforeUpdate->updated)->beforeDestroy -> destroyed
created : function(){...
mounted
updated
destroyed
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// a computed getter
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
DOM-based template
not string based, so template like '<div>1</div><div>2</div>' does not work
bind DOM to data, compiles under the hood the templates into virtual DOM render functions
can directly write render functions if familiar with virtual DOM instead of templates, + optional JSX
directives ("v-xxx" attributes)
supports Javascript expressions
in the data scope of owner Vue instance
with restriction - can only contain a single expression (statement, if-else etc. not work)
can have modifiers
"v:on:submit.prevent=... : call event.preventDefault()
sand boxed
Check API reference for more
Make in-template expression simple and declarative. For the rest, use "computed" object (side-by-side with "data"):
computed : { a_computed_property : function() { return this.some_property.some_operation.... }
"this" is the Vue (vm) instance
vm.a_computed_property : be used as a getter function
use: {{ a_computed_property }}
cached based on dependencies
not reactive dependency (Date.now()) won't update
computed setter: { a_computed_property : {get: function(){...}, set:function(newValue){...}}}
for example, update first/last name when full name changes
methods : { a_computed_property : function() { return this.some_property.some_operation.... }
use: {{ a_computed_property() }}
not cached, always run when re-render happens
watch : { a_watched_property : function(val) { this.a_model_property = val + ...}, b_watched_property: function(val){...}}
use: when either of the watched properties change, the corresponding function is called
don't over-use, often "computed" or "method" is much better for calculating compound property
watch an input: <input v-model="question">
Imperative : vm.$watch(watched_expression_or_function, callback_arg_old_new_value, [options])
Special treatment of v-bind:class & v-bind:style to make life easier
Object syntax
<div v-bind:class="{ some_class: some_class_is_active_true_or_false }"></div>
<div v-bind:class="classObject_holding_class_and_true_false"></div>
a plain "class=" can co-exist with the binding
can use computed property
Array syntax
<div v-bind:class="[class_data_property_1, class_data_property_2]"></div>
will find the value of the data property to render as class name
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
possible to use object syntax within array
With components
...
Binding inline styles
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> // bind properties of data
<div v-bind:style="styleObject"></div> // directly bind a style object
<div v-bind:style="[baseStyles, overridingStyles]"></div> // multiple style objects for overriding
Auto-prefixing : will auto detect and add prefix
Multiple values: <div v-bind:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
render the last value that the browser supports
v-if v-else v-else-if
<p v-if=”some_condition”>yes</p><p v-else>no</p>
to group more than one elements, <template v-if=”some_condition”>...</template>
v-else & v-else-if element must follow immediately an if / else-if
key
vue often reuse elements for efficiency.
Side effect – for input, user input will not reset
if not want to reuse, assign “key” attribute to element with unique values
v-show
like v-if
but always render element, only toggle “display” attribute
does not support else, nor template
preferred for frequent toggle – for lower computation cost
v-for
<li v-for=”item in items”>{{item.some_property}}</li>
works with component, but needs to bind explicitly (so component does not couple to for)
<my-component v-for=”(item,index) in items” v-bind:item=”item” v-bind:index=”index” v-bind:key=”item.id”>
key is required in this case
inside v-for block, full access to parent scope properties
v-for=”(item, index) in items” - index
“item of items” also works
works with template, <template v-for=”item in items”>
v-for-object
<ul id=”v-for-nameOfAnDataObject”><li v-for=”value in nameOfAnDataObject”>{{value}}</li></ul> - loop through values
<div v-for=”(value, key) in nameOfAnDataObject”>
<div v-for=”(value, key, index) in nameOfAnDataObject”>{{index}}{{key}}{{value}}
order not consistent
v-for in range
v-for=”n in 10”
v-for with v-if
v-for takes higher priority (loop over if)
<div v-for=”item in items” v-if=”item.shouldRender”>
key
when updating, it uses “in-place patch”
does not move DOM
patch each element in-place
efficient, but only suitable when
render output does not rely on child component state or temporary DOM state (input)
to help vue reuse element, give a hint to provide a unique key for each item
<div v-for=”item in items” :key=”item.id”>
it also provide id to nodes
RECOMMENDED – whenever possible, unless
item is simple, or
intentionally to get performance gains
Observed array
mutation: vue wraps an observed array’s mutation methods
push / pop
shift / unshift
splice
sort
reverse
replacement : can use new array returned from these methods to replace old array
example: app1.items = app1.items.filter(...)
filter
concate
slice
Caveats : see "Reactive Caveats"
Sorting / Filtering
use computed properties
use method (when computed properties not fesible, e.g. in nested for)
<button v-on:click=”//some javescript”>Action</button>
<button v-on:click=”nameOfMethod”>
methods:{nameOfMethod:function(event){...
<button v-on:click=”nameOfMethod(someParameter)”>
<button v-on:click=”nameOfMethod($event)”> this passes the original DOM event
modifiers (can use multiple: v-on.stop.prevent=”...”, order matters)
.stop – stop propagation (DOM)
.prevent – prevent default (DOM)
.capture – event of a child element is first handled here then child (DOM)
.self – only handle event for self not a child (DOM)
.once – trigger at most once (DOM+component event)
.passive – allow default behavior (scrolling, for example) to happen immediately instead of waiting for completion of handler – so handler cannot prevent default behavior but makes response better. Not to be used with .prevent, obviously
Keyboard events
<input v-on:keyup.13=”submit”... call vm.submit() when key up & code 13
<input v-on:keyup.enter=... use alias for key
enter tab delete esc space up down left right
or any name via KeyboardEvent.key in lower case: page-down
or define custom key modifier aliases Vue.config.keyCode.f1 = 112
<input @keyup.enter=... shorthand
<input @keyup.alt.67=”altC”...
.ctrl .alt .shift .meta (apple command / window key)
add .exact at end : needs the exact combination (for example, only ctrl without shift / alt)
Click events
modifiers: .left .right .middle
Basics
v-model create two-way binding
<input v-model=”message” placeholder=”edit me”>
will ignore initial value attributes (value, checked, selected etc.) and always use model data
Inputs
text <input...
for IME input (CJK) v-mode does not update during composition – use input event if desired
<textarea v-model=”...
don’t use {{ value }}
checkbox <input type=”checkbox” id=”someId” v-model=”value”>
value : true / false (unless binding used, see below)
true / false
multiple checkboxes bound to same array
static “value” attribute or binding
<input type=”checkbox” id=”idOne” value=”One” v-model=”checkedItemsArray”>
radio <input type=”radio” id=”choiceOne” value=”one” v-model=”pickedValue”>
static value, or v-bind:value=”someValue”
select <select v-model=”selected”><option disabled value=””>Please choose one</option><option>value</option></select>
the disabled initial selection is important for iOS to work well
static value or binded value
to bind non-static value, use v-bind
<input type=”checkbox” v-model=”something” true-value=”yes” false-value=”no”>
this does not affect the input’s “value” attribute, and not submitted in form
<option v-bind:value=”{prop1:value1,prop2:value2}”>
Modifiers (example: v-model.lazy)
.lazy – sync after change event, not input event
.number – cast input to number (type=”number” still returns a string)
.trim – trim automatically
Custom inputs works with v-model
Mixins
an object, contain any component options
to use, put in an array in 'mixins' property
when used by component, all options will be mixed into the component
var Component = Vue.extend({mixins: [myMixin]});
var componentInstance = new Component();
option merging
data : shallow merge (one property deep), component taking priority in conflict
hook functions: into an array and all get called, mixed in get called before component's own hook
options expecting object values (methods, components, directives)
merged into same object
component's property takes priority in conflict
global mixins (to EVERY instance)
Vue.mixin({...});
see document
custom options merge strategies
self define mixin logic - see document
Custom directives
allow low-level manipulation of DOM element
register global
Vue.directive('focus',{ inserted: function(el){el.focus();}})
register locally
directives:{focus:{inserted: function(el)...
use
<input v-foucs>
hook functions
bind - called only once, when bound to element (do setup work)
inserted - bound element inserted to parent node (parent not necessarily in document)
update - see document
componentUpdated - see document
unbind
...
Render functions & JSX
instead of template, in component options object
render: function(createElement) { return createElement( 'h'+this.level, this.$slots.default)}, // use createElement function to create element and return
...
Plugins (no strictly defined scope)
...
Filters
register global
Vue.filter('capitalize', function(value){return ...//capitalized value});
register locally
filters:{capitalize:function(value){...
use
in mustaches: {{ message | capitalize }}
in v-bind: v-bind:id="rawId | formatId"
...
Without build tools - use "vue.min.js"
With tools
determined by process.env.NODE_ENV
warnings will be stripped by minifiers
see document
template compile
in DOM or in-Javascript template string
compiled on the fly
check Vue version - use "vue/dist/vue.js" to include compiler
use single-file components (see below)
vue-template-loader for webpack
can separate javascript & template, translates template into js render functions
CSS
singler-file components: injected dynamically via javascript
small run time cost
"flash unstyled content"
extract css across all components into same file
webpack + vue-loader https://vue-loader.vuejs.org/en/configurations/extract-css.html
runtime error tracking
Vue.config.errorHandler - config function, good idea to hook with Sentry (official integration)
Problem with using global registration
forcing unique name, lacks syntax highlight, no CSS into components, no build step
Editor: for Atom - apm install language-vue-component
.vue template
<template>
it will become the template of the options object
<script>
<style>
global, will affect all pages
https://blog.bitsrc.io/11-vue-js-component-libraries-you-should-know-in-2018-3d35ad0ae37f