16/09/2018, 22:56

Các khái niệm cơ bản trong Vuex

State – trạng thái Vuex sử dụng một cây state duy nhất, đối tượng này sẽ chứa tất các state của ứng dụng, như vậy bạn chỉ có duy nhất một kho lưu trữ cho mỗi ứng dụng, điều này làm cho việc xác định các state là dễ dàng. Khái niệm cây state duy nhất không làm mất đi tính module hóa. ...

State – trạng thái
Vuex sử dụng một cây state duy nhất, đối tượng này sẽ chứa tất các state của ứng dụng, như vậy bạn chỉ có duy nhất một kho lưu trữ cho mỗi ứng dụng, điều này làm cho việc xác định các state là dễ dàng. Khái niệm cây state duy nhất không làm mất đi tính module hóa.
Để sử dụng các state trong Vue component, chúng ta sẽ lấy các state và trả về trong thuộc tính computed của component:

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

Mỗi khi store.state.count thay đổi, thuộc tính computed sẽ được tính toán lại và một trigger được tạo ra cho các DOM liên quan. Trong ứng dụng thiết kế dạng module, cần import store ở những nơi component sử dụng state. Vuex cung cấp cơ chế giúp sử dụng store cho tất cả ứng dụng :

const app = new Vue({
  el: '#app',
  // provide the store using the "store" option.
  // this will inject the store instance to all child components.
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

Các component con có thể truy xuất store thông qua this.$store

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}


Getter – bộ lọc trạng thái
Đôi khi chúng ta cần lấy các state dựa vào việc tính toán, lọc bỏ các state được cung cấp bởi store, ví dụ:

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


Nếu nhiều component cần làm điều này, chúng ta có thể định nghĩa getter trong store để thực hiện.

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)
    }
  }
})

Khi đó chúng ta có thể truy xuất các state đã được lọc này bằng cách sử dụng cú pháp state.getter.doneTodos.

Mutations – thay đổi trạng thái
Trạng thái không thể thay đổi trực tiếp mà chỉ được thay đổi thông qua commit và mỗi commit này là một hành động được thực hiện tại action. Vuex mutation đóng vai trò hay sự kiện để thay đổi state.

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // mutate state
      state.count++
    }
  }
})


Bạn không thể gọi trực tiếp một handler của mutation, cách thức gọi các handler này sẽ giống như việc đăng ký các sự kiện: “Khi mutation với dạng increment được trigger, gọi đến handler này”, cách thức này được thực bằng cách sử dụng store.commit. Bạn có thể truyền thêm tham số cho các handler trong mutation:

mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit('increment', 10)

Action – hành động Là nơi chứa các hành động như lấy dữ liệu api từ serve hay một hành động làm thay đổi dữ liệu trong CSDL( thêm, sửa, xóa) và hơn thế nữa action commit các thay đổi state ở mutation. Action có thể chứa các hoạt động không đồng bộ.

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})


Module
Vuex sử dụng cây trạng thái duy nhất, tất cả các trạng thái của ứng dụng được đưa vào một đối tượng, như vậy khi ứng dụng phát triển lên, store có thể phình lên rất nhiều. Vuex cho phép chia nhỏ store thành các module nhỏ hơn, mỗi module cũng có state, mutation, action, getter và thậm chí còn cho phép các module lồng nhau.

Chú ý, các mutation và getter, tham số đầu tiên sẽ là state cục bộ của module:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA's state
store.state.b // -> moduleB's state

 

+2