---
# System prepended metadata

title: Vue

---

# 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
        }
    },
});
```
![](https://i.imgur.com/V73Nxzr.png)

==更簡易的縮寫方式==

在屬性前方直接加上 `:` 就可將 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 }
});
```

![](https://i.imgur.com/apVg7HU.png)

#### 修飾子

`.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 }
});
```

![](https://i.imgur.com/CX2VW1y.png)

#### 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 }
});
```

