---
# System prepended metadata

title: Vue 常用 API
tags: [Vue, Vue.js]

---

Vue 常用 API
===
###### tags: `Vue.js` `Vue`

官網：https://cn.vuejs.org/v2/api/

## 使用 **Extend** 做元件重複部分的Reuse

```javascript=
const newExtend = Vue.extend({
    ...
    mounted() {
        console.log('Extend mounted', this);
    }
});
```
```javascript=
Vue.component('extend-cmpt-one', {
    ...
    extends: newExtend
});
```
```javascript=
Vue.component('extend-cmpt-two', {
    ...
    extends: newExtend,
    mounted() {
        console.log('extend-cmpt-two mounted');
    }
});
```

實作範例：https://codepen.io/lala-lee-jobs/pen/wvaYzBB

## 使用 **Filter** 自定義畫面資料格式

### 寫在元件內 (Local registration)

```javascript=
Vue.component('my-cmpt', {
    ...,
    filters: {
        dollarSign(n) { return `$ ${n}`; },
        currency(n) { return ...; }
    },
    ...
});
```

### 寫在全域 (Global registration)
```javascript=
Vue.filter('dollarSign', (n) => { return `$ ${n}`; });
Vue.filter('currency', (n) => { return ...; });
```

實作範例：https://codepen.io/lala-lee-jobs/pen/JjdmRez

## 無法寫入的資料，使用$set做設定

**Vue Reactivity (Vue 的響應式原理)**
https://cn.vuejs.org/v2/guide/reactivity.html

有些資料無法預先定義資料格式，例如ajax下來的資料內容，因為Vue會封裝成自己的資料結構(...)，使用getter/setter方法去存取(Vue會在初始化實例時對屬性執行getter/setter轉化)

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

在HTML模版只會反應Vue綁定好的資料結構，所以需要使用$set把資料寫到Vue的結構內，才能被Vue監控變化用以重新渲染畫面

> 如果要動態設定某個物件的值
> const someObj = { propname: 2 };
> 這樣設定是不會直接反應在畫面上，需要透過set的方式

* 使用全局Vue.set設定的方式
Vue.set(object, propertyName, value) 

```javascript=
Vue.set(this.someObj, 'propname', 2);
```

* 使用Vue實例的方式，這也是全局Vue.set方法的別名
this.$set(object, propertyName, value);

```javascript=
this.$set(this.someObj, 'propname', 2)
```

### 補充

>**物件部分：一開始沒有被註冊到的物件，不會響應式更新**
>* 方法一：在 data 中要把所有需要響應式的資料設定進去 (預先定義)
>* 方法二：動態添加新的響應式屬性 Vue.set(...) or this.$set(...)
>* 方法三：建立新的物件 Object.assign({}, obj1, obj2, ...);

>**陣列部分：利用陣列索引直接設值時，沒有辦法產生響應式的變化**
>* 方法一：使用 Vue 可觀察到的陣列方法 (可促使畫面重新渲染)
>`push()`、`pop()`、`shift()`、`unshift()`、`splice()`
>`sort()`、`reverse()`
>* 方法二：使用Set方法動態設定 
>`Vue.set(array, index, value)`
>`this.$set(array, index, value)`

## Mixin 混合多個元件的行為

```混合mixins```和```繼承extends```

其實兩個都可以理解為繼承，用來使元件部分的程式碼可以Reuse

* mixins 接收物件陣列（可理解為多繼承）
```
mixins: [mixinObj1, mixinObj2]
```

* extends接收的是物件或函式（可理解為單繼承）
```
extends: extendObj
```

```javascript=
const extendObj = {
    created () {
        console.log('extendObj created')
    }
};

const mixinObj1 = {
    created () {
        console.log('mixinObj1 created')
    }
};
const mixinObj2 = {
    created () {
        console.log('mixinObj2 created')
    }
};

Vue.component('my-cmpt', {
    extends: extendObj,
    mixins: [mixinObj1, mixinObj2],
    created () {
        console.log('my-cmpt created')
    }
}
```

執行範例：https://codepen.io/lala-lee-jobs/pen/YzXJgOL

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

可以發現同時宣告extends和mixins時，extends的Lifecycle觸發的時機點會早於mixins，mixins則早於元件本身

## 使用 Directive 開發自己的互動 UI

### 宣告 Directive

#### 全域

```
Vue.directive('focus', {
  inserted: function (el) {
    el.focus()
  }
});
```

#### 局部 

```
directives: {
  focus: {
    inserted: function (el) {
      el.focus()
    }
  }
}
```

### 使用 Directive
```
<input v-focus>
```

### Directive Hook Function

* bind：只調用一次，Directive第一次綁定到元素時調用。初始化設置可在此實作。
* inserted：被綁定Directive的元素插入父節點時調用
* update：所在Component的VNode更新時調用，但是可能發生在其子VNode更新之前。Directive的值可能發生了改變，也可能沒有。但是你可以通過比較更新前後的值來忽略不必要的模板更新
* componentUpdated：Directive所在Component的 VNode 及其子VNode全部更新後調用。
* unbind：只調用一次，Directive與元素解綁時調用

### Directive Hook Arguments

* el：Directive 所綁定的元素，可以用來直接操作DOM。
* binding：Object，包含以下屬性：
    * name：不包括v-前綴的Directive名稱
    * value：Directive的綁定值，例如：v-my-directive="1 + 1"中，綁定值為2。
    * oldValue：Directive綁定的前一個值，僅在update和componentUpdated鉤子中可用。無論值是否改變都可用。
    * arg：傳給Directive的參數，可選。例如v-my-directive:foo中，參數為"foo"。
* vnode：Vue編譯生成的虛擬節點。
* oldVnode：上一個虛擬節點，僅在update和componentUpdated鉤子中可用。

實作範例：https://codepen.io/lala-lee-jobs/pen/mdJQMRv

