---
# System prepended metadata

title: Vuex Introduction

---

# Vuex Introduction

###### Speaker: Dr. Sang Nguyen

---

### Tại sao lại sử dụng Vuex
- Không thể dùng các phương pháp khác như props, event bus để trao đổi dữ liệu giữa các component vì sẽ quá phức tạp với dự án trung bình, lớn.
- Vuex cho ta khả năng lưu trữ và chia sẻ data trong mà không phải đánh đổi về performance, testability hoặc maintainability.

---

### UI = f(state)

![](https://flutter.dev/assets/development/data-and-backend/state-mgmt/state-management-explainer-5495afe6c3d6162f145107fe45794583bc4f2b55be377c76a92ab210be74c033.gif)

Nguồn: https://flutter.dev/docs/development/data-and-backend/state-mgmt/intro

---

## Vuex là gì?



#### Định nghĩa
- Là Pattern và Library quản lý state trong VueJS.

#### Tính chất
- Store tập trung (centralized store).
- Có những qui tắc để dữ liệu chỉ có thể được thay đổi theo kiểu cách tiên đoán được (predictable fashion).
- one-way data flow

---

#### Nói 1 cách dễ hiểu
- Vuex là 1 cách để nhiều components dùng chung state.
- Mỗi view có thể phụ thuộc vào 1 phần của state chung đó.
- Nhiều action khác nhau (từ các view khác nhau) có thể thay đổi/cập nhật chung 1 vài thành phần của state.
- Tham khảo:
    - Single source of truth
    - Redux: predictable state container

---

### 1-way data flow chung
![](https://i.imgur.com/x7Agehc.png)



---

### Vuex diagram

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


---

### Nhắc lại Single File Component (SFC)
```javascript=
<template>
    <p>{{ greeting }} World!</p>
</template>

<script>
    module.exports = {
        data() {
            return {
                greeting: 'Hello'
            }
        }
    }
</script>

<style scoped>
    p {
        font-size: 2em;
    }
</style>
```

---

- Code HTML, CSS, script của một Component trong cùng một file.
- Tại sao?

---

## Câu trả lời

- Làm giảm số lượng file.
- Đồng nhất, move/copy 1 component từ nơi này sang nơi khác (dự án này qua dự án khác) thì nó luôn "đủ bộ".
- Ví dụ: Coupon của Phòng chăm sóc khách hàng và Phòng giáo dục.

---

## Các thành phần của Vuex

**Các thành phần**
- State
- Mutation 
- Actions
- Getters

---

## State
- State là một object (singleton) chứa các properties được dùng chung trong nhiều nơi khác nhau của ứng dụng. 
- State gần giống 1 global object, ngoại trừ:
    - Vuex store có tính reactive: những **Component** sẽ reactive với **State**, tự động cập nhật nếu State thay đổi.
    - Ta không thể thay đổi state một cách trực tiếp.
    - Thay đổi state bắt buộc phải commit một mutation.

---

- Cách khai báo
```javascript=
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  }
})
```
- Cách sử dụng
```javascript=
// Cách 1
computed: {
    count() { return this.$store.state.count}
}
```

---

```
// Cách 2
import { mapState } from 'vuex'



computed: mapState([
  // map this.count to store.state.count
  'count'
])
```

---


## Mutation
Là cách duy nhất trong Vuex để thay đổi state



```javascript=
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

store.commit('increment')
```

---

#### Commit with Payload
```javascript=
//Khai báo
mutations: {
  increment (state, payload) {
    state.count += payload
  }
}


//Sử dụng
store.commit('increment', 10)
```

---

#### Object-Style Commit
> Không khuyến cáo - Tự tìm hiểu

---

#### Nguyên tắc sử dụng Mutations dựa trên Vuex Reactive Rules

---

#### Using Constants for Mutation Types
- Một file cho thấy cái nhìn tổng quan về mutations.
- Tránh khai báo trùng tên mutation.
- Đây 1 là good practice - Nên follow.

---

#### Mutations Must Be Synchronous
- Luôn luôn là code synchronous (Không có callback/promise/async/await)

---

## Action
- Nếu Mutation để commit state change thì Action để commit mutation
- Được phép dùng asynchronous
```
Mutation: setCount
this.state.count = a;

Action
store.commit('setCount', a);
```

---

## Getter
- Sử dụng khi cần thực hiện một operation gì đó từ dữ liệu của **State**.
- Có thể hiểu như là những **computed properties** trong Store.
- Tránh trùng lặp code.
- Ví dụ:
Thay vì phải viết lại một computed cho nhiều component

```javascript=
computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}
```

---

Thì có thể khai báo getter trong store để sử dụng được mọi nơi

```javascript=
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})
```

---

Sử dụng getter
```javascript=
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
```
Sử dụng mapGetters trong phần computed của các components

```javascript=
import { mapGetters } from 'vuex'
computed: {
    ...mapGetters([
        'doubleCounter',
        'stringCounter'
    ]),
    ourOwn()
}
```

---

## Phát biểu cảm nghĩ về Vuex
- Ban đầu: Quá nhiều qui tắc làm ta gò bó.
- Sau 2 tháng: Những qui tắc cho ta được tự do hơn.
