Приложение Vue начинается с создания нового экземпляра Vue через функцию:

var vm = new Vue({
  // опции
})

При создании экземпляра Vue необходимо передать объект опций. Приложение Vue состоит из корневого экземпляра Vue, созданного с помощью new Vue, опционально организованного в дерево вложенных, повторно используемых компонентов. Например, дерево компонентов TODO-списка может выглядеть так:

Root Instance
└─ TodoList
   ├─ TodoItem
   │  ├─ DeleteTodoButton
   │  └─ EditTodoButton
   └─ TodoListFooter
      ├─ ClearTodosButton
      └─ TodoListStatistics

Все компоненты Vue также являются экземплярами Vue и поэтому принимают тот же объект параметров.

Данные и методы

После создания экземпляра Vue в него добавляются все свойства найденные в объекте data. Если значения свойств изменяются, представление будет обновляться вместе с новыми значениями.

// Наш объект data
var data = { a: 1 }

// Объект добавляется в экземпляр Vue
var vm = new Vue({
  data: data
})

// Ссылки указывают на один и тот же объект!
vm.a === data.a // => true

// Изменение свойства экземпляра
// будет влиять на оригинальные данные
vm.a = 2
data.a // => 2

// ... и наоборот
data.a = 3
vm.a // => 3

Когда эти данные изменятся, представление будет перерендерено (повторно отображено). Следует запомнить, что свойства в data будут реактивными, только если они существовали при создании экземпляра. Это означает, что если вы добавите новое свойство, например:
При изменении этих данных представление будет повторно отображено. Свойства в data будут реактивными, когда они существовали при создании экземпляра. Если же добавить новое свойство позже: 

vm.b = 'hi'

То изменения в b не будут вызывать никаких обновлений отображения. Поэтому, чтобы использовать свойство для обновления, нужно установить начальное значение при создании экземпляра.

data: {
  newTodoText: '',
  visitCount: 0,
  hideCompletedTodos: false,
  todos: [],
  error: null
}

Исключением из правила является метод Object.freeze(), превращающий изменение существующих свойств.

var obj = {
  foo: 'bar'
}

Object.freeze(obj)

new Vue({
  el: '#app',
  data () {
    return {
      obj
    }
  }
})
<div id="app">
  <p>{{ obj.foo }}</p>
  <!-- мы теперь не можем обновить obj.foo! -->
  <button @click="obj.foo = 'baz'">Изменить</button>
</div>

Кроме свойств объекта data, экземпляры Vue предоставляют ряд полезных свойств и методов экземпляра, которые именуются с префикса $, чтобы отличаться от пользовательских свойств.

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})

vm.$data === data // => true
vm.$el === document.getElementById('example') // => true

// $watch — это метод экземпляра
vm.$watch('a', function (newValue, oldValue) {
  // Этот коллбэк будет вызван, когда изменится `vm.a`
})

Хуки жизненного цикла экземпляра

Любой экземпляр Vue при создании проходит через последовательность шагов инициализации — настраивает наблюдение за данными, компилирует шаблон, монтирует экземпляр в DOM, обновляет DOM при изменении данных. 
Во время этих шагов вызывает функции - хуки жизненного цикла, которые дают добавлять свой собственный код на определённых этапах.
Например, хук created используется для выполнения кода после создания экземпляра:

new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` указывает на экземпляр vm
    console.log('Значение a: ' + this.a)
  }
})
// => "Значение a: 1"

Есть также хуки, которые вызываются на разных стадиях жизненного цикла экземпляра, например mounted, updated, и destroyed. Все хуки вызываются с контекстной переменной this, ссылающейся на вызывающий экземпляр Vue.