# Vue
## Vue 與其他框架的差異?
tag: `輕量`、`入門容易`
* 資料綁定&操作網頁元件
* 關注在狀態與畫面的同步
* 易方便和其他函式庫&工具鏈使用
## 實體物件
### 掛載方式
掛載對象可以是 CSS Selector 也可以是 DOM 物件
**透過 $mount 掛載**
```javascript
const vm = new Vue({
data: {
message: 'Hello World!'
}
});
vm.$mount('#app');
```
**透過 options `el` attribute 掛載**
```javascript
const vm = new Vue({
el: '#app'
})
```
## 實體核心 Options
```javascript
const vm = new Vue({
//options
});
vm.$mount('#app');
```
### data
作為定義實體的屬性,回傳的狀態以 `Key-Value` 的形式
Vue 會自動將 data 內的屬性都加上 `getter` `setter` 來監控狀態更新
:::danger
如果以 _ 或 $ 命名的屬性將不會被加上 getter & setter
:::
```javascript
const vm = new Vue({
data: {
message: 'Apple'
}
});
vm.$mount('#app');
```
透過 {{ }} 文字模板的方式,就可將 `data` 的內容 Render 至畫面
```htmlembedded
<div id="app">
{{ message }}
</div>
```
Vue 實體被建立後就會自動為實體加上 `$data` 屬性,就可以透過 `vm.$data.xxx` 進行操作
```javascript
const vm = new Vue({
data: {
message: 'Apple'
}
});
vm.$mount('#app');
vm.$data.message = 'banana';
```
==共用污染==
如果 Vue 物件直接使用了同一個 Object 則容易會有污染問題
```javascript
const obj = {
Name: 'Apple'
}
const vm1 = new Vue({
el: '#app',
data: obj
})
const vm2 = new Vue({
el: '#app',
data: obj
})
```
若使用 `vm2.$data.Name` 更改 Value,則會一起更動到
可以使用解構 `{...obj}` 來避免此種情形
### template
可直接使用 template 屬性來決定 HTML 內容
一個 template 只會有一層元素,且必須要有根元素
```javascript
const vm = new Vue({
el: '#app',
template: '<div>Hello {{ Name }}</div>',
data: {
name: 'Apple'
}
})
```
### methods
負責處理邏輯
```htmlembedded
<div id="app">
{{ getNameLength() }}
</div>
```
```javascript
const vm = new Vue({
el: '#app',
data: {
name: 'Apple'
}
methods:{
getNameLength: function(){
return this.name.length
}
}
})
```
### computed
負責處理計算邏輯
```htmlembedded
<div id="app">
{{ getTotal }}
</div>
```
```javascript
const vm = new Vue({
el: '#app',
data: {
count: 1,
price: 5
}
methods:{
getTotal: function(){
return this.count * this.price;
}
}
})
```
#### computed & method 兩者不同之處
`computed` 會監控自己關注的屬性並將結果進行暫存,不會重複執行
`method` 則每次呼叫就會執行
`computed` 無法帶入參數
`method` 可帶入參數
`computed` 可以透過 set 更改自己關注的屬性本身
### filters
處理純粹的加工,將相同的輸入丟入,永遠都會回傳相同的輸出,並且不對任何該函數以外的任何作用域產生影響。
使用 pipe 在文字模板內進行表示
pipe 前方作為 parameter 傳入 filters function 裏
```htmlembedded
<div id="app">
{{ name | getLowerCase }}
</div>
```
```javascript
const vm = new Vue({
el: '#app',
data: {
name: 'Apple'
}
filters:{
getLowerCase: (value) => {
return value.toLowerCase();
}
}
})
```
## 指令
### 屬性綁定 v-bind
透過 v-bind 可以針對 HTML 元素的 Attribute 進行資料綁定
```htmlembedded
<div id="app">
<span v-bind:title="message">Hover On Text</span>
<input v-bind:value="count()" />
</div>
```
```javascript
const appData = {
message: "Apple 測試",
number: 1
};
const vm = new Vue({
el: "#app",
data: { ...app },
methods: {
count: function(){
return this.number + 1
}
},
});
```

==更簡易的縮寫方式==
在屬性前方直接加上 `:` 就可將 Attribute 改為 v-bind 綁定的 Attribute
```htmlembedded
<div id="app">
<span :title="message">Hover On Text</span>
<input :value="count()" />
</div>
```
### 表單綁定 v-model
v-model 可以與表單元素進行雙向綁定,進行更新元素內容
```htmlembedded
<div id="vmodel">
<input v-model="message" />
<span>表單內容: {{ message }}</span>
</div>
```
```javascript
const app = {
message: "Apple 測試",
number: 1
};
var vmodel = new Vue({
el: "#vmodel",
data: { ...app }
});
```

#### 修飾子
`.lazy` 在 onBlur 時才會更新 data
`.num` 將 text 轉型為 number
`.trim` 將 text 前後空白移除
### 模板綁定 v-text / v-html / v-pre / v-once
#### v-text
除了使用 `{{ }}` 作為文字模板,也可以透過 v-text 來處理模板
```htmlembedded
<div id="vmodel">
<input v-model="message" />
<span v-text="message"></span>
</div>
```
```javascript
const app = {
message: "Apple 測試",
number: 1
};
var vmodel = new Vue({
el: "#vmodel",
data: { ...app }
});
```
與 `{{ }}` 最大不同之處是 `v-text` 會將 HTML 標籤內的 Inner Text 覆蓋
#### v-html
與 `v-text` 不同,概念上很像 JavaScript 裡的 `innerText` & `innterHTML`
`v-html` 會將內容的 HTML 語法進行渲染
```htmlembedded
<div id="vmodel">
<div v-html="title"></div>
</div>
```
```javascript
const app = {
title: "<h1>Apple 讚</h1>",
};
var vmodel = new Vue({
el: "#vmodel",
data: { ...app }
});
```

#### v-once
內容只會渲染第一次,不會隨著資料更新
#### v-pre
加上指令 v-pre 後,就不會解析 `{{ }}` 的資訊
### 樣式綁定
可以透過剛才的 `v-bind` 與 `class` `style` 進行簡單的樣式控制
```htmlembedded
<div id="vclass">
<div :class="{ 'active': isActive }"></div>
</div>
```
```css
.active {
color: 'blue'
}
```
```javascript
const app = {
isActive: true,
};
var vclass = new Vue({
el: "#vclass",
data: { ...app }
});
```
### 事件綁定 v-on
#### v-on
`v-on` 為 Vue 與事件進行綁定的指令,也可縮寫為 `@event`
```htmlembedded
<div id="von">
<span>Now Count : {{ count }}</span>
<button @click="add()"></button>
</div>
```
```javascript
const app = {
count: 1,
};
var vclass = new Vue({
el: "#von",
data: { ...app },
methods:{
sum: function(){
return this.count++;
}
}
});
```
#### event 物件
v-on 在 method 沒有參數時會預設將 event 做為參數帶入
```htmlembedded
<div id="von">
<span>Now Count : {{ count }}</span>
<button @click="sum"></button>
</div>
```
```javascript
const app = {
count: 1,
};
var vclass = new Vue({
el: "#von",
data: { ...app },
methods:{
sum(event){
console.log(event); // event object Button
return this.count++;
}
}
});
```
有參數時使用 $event 即可帶入
```htmlembedded
<div id="von">
<span>Now Count : {{ count }}</span>
<button @click="sum(amount, $event)"></button>
</div>
```
```javascript
const app = {
count: 1,
amount: 10
};
var vclass = new Vue({
el: "#von",
data: { ...app },
methods:{
sum(amount, event){
console.log(event); // event object Button
return this.count + amount;
}
}
});
```
#### 修飾子
`.stop` 阻止事件冒泡,形同 `event.stopPropagation()`
`.prevent` 阻止預設事件行為,形同 `event.preventDefault()`
`.capture` 捕獲事件,由上而下執行
`.self` 只觸發由事件本身產生的行為,子元素傳遞的不會觸發
`.once` 事件只觸發一次
`.passive` 被動事件監聽,告訴瀏覽器該元素是否可以被 prevent
#### 鍵盤修飾子
`.enter` `.meta` `.ctrl` `.page-down`
`.exact` 判斷確定是由該鍵盤按鍵
#### 滑鼠修飾子
`.left` `.middle` `.right`
### 條件綁定 v-if / v-show
#### v-show
`v-show` 主要控制元素顯示與隱藏
控制隱藏的方式是使用 `display: none`
#### v-if
直接動態刪減元素,元素會直接新增或消失
可以搭配 `v-else-if` `v-else`
若有多重相同條件需要一起判斷時可以使用 `<template></template>`
```htmlembedded
<div id="vif">
<template v-if="value === 'A'">
<span>Apple</span>
<span>Arrange</span>
</template>
<template v-else>
<span>Book</span>
<span>Bamboo</span>
</template>
</div>
```
```javascript
const app = {
value: 'A'
};
var vclass = new Vue({
el: "#vif",
data: { ...app }
});
```
:::info
Vue 為了提高網頁渲染效率,在渲染畫面時會先使用已存在的元素
:::
但有的時候元素身為不同的個體卻被當成同一個,因此可以使用 `key`
有 `key` 屬性的元素將會被重新渲染
### 陣列渲染 v-for
```htmlembedded
<div id="vfor">
<ul>
<li v-for="item in arr"></li>
<li v-for="(index, item) in arr"></li>
</ul>
</div>
```
```javascript
const app = {
arr: ['apple, banana, orange']
};
var vclass = new Vue({
el: "#vfor",
data: { ...app }
});
```