# Vue.js 文件閱讀 part 2- The Vue Instance
---
tags: Javascript relate
---
###### tags: `Javascript, Vue.js`
# 創造Vue實體 (Creating a Vue Instance)
* 所有的Vue app 都會從創造實例(Instance)開始
* 裡面的options處就是我們操作的地方,可以瀏覽[ API reference](https://vuejs.org/v2/api/#Options-Data)來做操作
```javascript=
var vm = new Vue({
// options
})
```
* 一個Vue app通常會有會有個root Vue instance由new Vue產生
* 伴隨著的是巢狀的樹組成的component,它具有可重複使用的特性
* 在ROOT下面的都是component的部分
```javascript=
Root Instance
└─ TodoList
├─ TodoItem
│ ├─ TodoButtonDelete
│ └─ TodoButtonEdit
└─ TodoListFooter
├─ TodosButtonClear
└─ TodoListStatistics
```
## 範例
index.js
```javascript=
var app = new Vue({
el:#app,
data: {
product: "Socks"
})
```
index.html
```htmlembedded=
<div id="app">
<h2>{{ product }} </h2>
</div>
```
* app使用el連接到html檔案內部的id = "app"的div
* 連結app內的data: poduct到html上{{product}}
* 藉由改變index.js 內 product的內容可以及時修改html內的{{product}}的內容
呈現在網頁上的結果

藉著改變屬性也可以及時修改頁面內容
```javascript=
app.product = 'Coat'
//印出結果變成Coat
app.product = "Compass"
//印出結果變成Compass
```


# 資料與方法(Data and Methods)
## $data
```htmlembedded=
<div id="app">{{msg}}</div>
```
```javascript=
let data = {
msg: '123123'
}
let vm = new Vue({
el: '#app',
data,
});
```
這兩個是相同的結果
```javascript=
vm.$data === data //true
data.msg === vm.msg //true
```
因此當我們操作
```javascript=
data.msg =456
vm.msg = 123
```
畫面也會如此響應
但是如果使用不存在的屬性時畫面則不會響,得使用不同的方法
```javascript=
vm.b = 'hi'
```
但是如果你知道可能稍後會有屬性會使用到,但目前得空著或是還未存在,因此就必須設預設值
比方說要規畫一個todoList app可能會使用到的data:
```javascript=
data: {
newTodoText: '',
visitCount: 0,
hideCompletedTodos: false,
todos: [],
error: null
}
```
## Object.freeze()
可以關閉reative,讓畫面不被響應
```htmlembedded=
<div id="app">{{msg}}</div>
```
```javascript=
let data = {
msg: 'hello Vue'
}
Object.freeze(data);
let vm = new Vue({
el: '#app',
data,
});
```
在這個情況下
```javascript=
data.msg =456
vm.msg = 123
```
畫面也不會有任何響應
並vm也會變成只能讀不能寫

## $前綴API
$這個符號代表Vue提供給我們的功能
如
$data,
$el,
$watch等等
[Instance Properties](https://vuejs.org/v2/api/#Instance-Properties)
# 生命週期裝置實例(Instance Lifecycle Hooks)
到特定的時間就會呼叫特定的函式
每個Vue實體都會經歷一連串的初始化階段舉例:
1. 需要設置好data observation
1. 編譯模板
1. 把Vue實體推到DOM上
1. 更新DOM當data被更新
在這個階段過程中也會跑一些functions被稱為**Lifecycle Hooks**,讓使用者寫自己的程式碼在特定的階段使用
## 範例
當Vue實體已經被創造時,created這個函式可以被使用:
```javascript=
new Vue({
data: {
a: 1
},
created: function () {
// `this` points to the vm instance
console.log('a is: ' + this.a)
}
})
// => "a is: 1"
```

在不同的階段還有其他的hooks會被呼叫例如:
所有的hook指向調用它的實體
* mounted
* updated
* destroyed
## 作者提醒
千萬不要使用箭頭函式在Vue實體,因為箭頭函示沒有this常常會導致報錯
```
Uncaught TypeError: Cannot read property of undefined
Uncaught TypeError: this.myMethod is not a function
```
使用一般的函式:
```javascript=
new Vue({
data: {
a: 1
},
created: function () {
console.log(this)
}
})
```
才能印出 Vu實體

使用箭頭函式:
```javascript=
new Vue({
data: {
a: 1
},
created: () => {
console.log(this)
}
})
```
只會印出外層的windows

## Lifecycle Diagram
從上方那張圖可以得知hook如下:
**beforeCreate**
Vue實體初始化後立刻呼叫此函式,不過此時Vue實體還未創建所以其中的設定都還未能使用(如data observation, event, watcher setup)
**created**
Vue實例創建完成後立刻呼叫此函式,已設置 data, computed properties, methods, watch/event callbacks,但尚未開始mounting階段,且 $el 還不能在此階段使用。
**beforeMount**
在mounting階段開始前被調用:render function首次被調用。
**mounted**
選項物件中的el被新創建的vm.$el替換,並掛載到到 vm 上,並調用mounted這個鉤子。
**beforeUpdate**
數據被更新時會調用,發生在 Virtual DOM re-render 和 patch 之前(連結:Day4: Virtual DOM),可以在此時更改狀態數據,並不會增加重新渲染的成本。
**updated**
由於數據更新導致 Virtual DOM re-render 和 patch 之後會調用updated這個鉤子。
不精確白話文為:由於updated被調用時,DOM 已經更新。所以在此時更新數據很可能會導致updated無限循環的被調用。
**beforeDestroy**
在 Vue Instance 被銷毀前被調用,因此 Vue Instance 在beforeDestroy中仍可運作。
不精確白話文為:Vue Instance 可以在此時做垂死前的掙扎。
**destroyed**
在 Vue Instance 被銷毀後被調用,此時 Vue Instance 所有東西會解除綁定,事件監聽也都會被移除,子實例也會被銷毀。
# 模板語法(Template Syntax)
未完待續~