Vue 2 Core Concepts: Reactive Views, Directives, and Component Architecture
Getting Started
Drop Vue into any page via CDN:
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
Create a mount point and an instance:
<div id="root">
<h1>{{ heading }}</h1>
</div>
<script>
new Vue({
el: '#root',
data () {
return { heading: 'Hello Vue!' }
}
})
</script>
Template Syntax & Reactivtiy
Text interpolation uses double curly braces:
<p>{{ message }}</p>
Vue tracks reactive dependencies; any change to message instantly updates the DOM.
MVVM Recap
- Model – plain JavaScript data (objects, arrays, primitives).
- View – the rendered DOM.
- ViewModel – the Vue instance that keeps the two in sync.
Built-in Directives
| Directive | Purpose | Example |
|---|---|---|
v-text |
raw text insertion | <span v-text="msg"></span> |
v-html |
HTML insertion | <div v-html="rawHtml"></div> |
v-show |
toggle display: none |
<p v-show="isVisible">Peek-a-boo</p> |
v-if / v-else-if / v-else |
conditional rendering | <h2 v-if="ok">Yes</h2> |
v-for |
list rendering | <li v-for="(item, i) in items" :key="i">{{ item }}</li> |
v-on |
event binding | <button @click.once="save">Save</button> |
v-bind |
dynamic attributes | <img :src="url" :class="{ active: isActive }"> |
v-model |
two-way form binding | <input v-model.trim="query"> |
v-pre |
skip compilation | <code v-pre>{{ raw }}</code> |
v-cloak |
hide un-compiled markup | [v-cloak] { display: none; } |
v-once |
render once | <span v-once>{{ staticText }}</span> |
Custom Directives
Global:
Vue.directive('focus', {
inserted (el) { el.focus() }
})
Local:
new Vue({
directives: {
focus: { inserted (el) { el.focus() } }
}
})
Hooks: bind, inserted, update, componentUpdated, unbind.
Hook parameters: el, binding, vnode, oldVnode.
Computed vs Watched vs Methods
Computed properties cache results until dependencies change:
computed: {
total () {
return this.items.reduce((sum, i) => sum + i.price, 0)
}
}
Watchers run side-effects:
watch: {
keyword (newVal, oldVal) {
this.fetchHints(newVal)
}
}
Methods execute on every render.
Filters (Vue 2 only)
Global:
Vue.filter('currency', v => `¥${v}`)
Local:
filters: { currency: v => `¥${v}` }
Usage: {{ price | currency }} or v-bind:id="rawId | slug".
Components
Global registration:
Vue.component('todo-item', {
props: ['task'],
template: `<li>{{ task.text }}</li>`
})
Local registration:
new Vue({
el: '#app',
components: {
'todo-item': {
props: ['task'],
template: '#todo-tpl'
}
}
})
Rules:
- Tmeplate must have a single root element.
datamust be a function returning a fresh object.- Use kebab-case in DOM (
my-component).
Parent ↔ Child Communication
Parent passes data down via props:
<child :msg="parentMsg"></child>
Child emits events upward:
this.$emit('update', newData)
<child @update="parentHandler"></child>
Lifecycle Hooks
new Vue({
beforeCreate () { /* no reactive data yet */ },
created () { /* data ready, DOM not mounted */ },
beforeMount () { /* template compiled, not in page */ },
mounted () { /* fully inserted; use $nextTick for children */ },
beforeUpdate () { /* reactive data changed, DOM not patched */ },
updated () { /* DOM patched */ },
beforeDestroy () { /* teardown logic */ },
destroyed () { /* all bindings removed */ }
})
Use vm.$destroy() to manually tear down an instance.
With these building blocks you can construct reactive, component-based UIs in Vue 2.