Store
ZMP cung cấp thư viện quản lý state. Phục vụ một centralized Store cho tất cả components trong ứng dụng.
Bạn vẫn có thể sử dụng các thư viện quản lý state khác như Redux.
Tạo Store
Đầu tiên cần tạo store. Tạo file store.js:
// Đầu tiên cần import createStore từ zmp-framework core
import { createStore } from 'zmp-core/lite';
// tạo store
const store = createStore({
// bắt đầu với state (dữ liệu sẽ lưu trong store)
state: {
users: []
// ...
},
// actions sẽ thao tác với state và xử lý các bất đồng bộ
actions: {
// context object chứa state của store được truyền vào dưới dạng đối số
getUsers({ state }) {
// gọi api
fetch('some-url')
.then((res) => res.jsstate
.then((users) => {
// gán users trả về cho state
state.users = users;
});
}
// ...
},
// getters cho phép lấy giá trị của state
getters: {
// context object chứa state của store được truyền vào dưới dạng đối số
users({ state }) {
return state.users;
}
}
});
// export store
export default store;
Store Parameters
storeParameters object:
State
state Một object chứ state của ứng dụng.
Actions
actions sử dụng để cập nhật state, tác vụ bất đồng bộ, gọi actions khác. Action handlers cung cấp một context object với store state và phương thức dispatch để gọi actions khác. Có thể truy xuất context.store để truy xuất state hoặc gọi actions với context.dispatch.
Tham số thư hai cung cấp data.
Nên cập nhật state bằng cách gán giá trị mới. Ví dụ:
// sửa đổi trạng thái hiện tại - NOT REACTIVE
state.users.push(...users);
// gán giá trị mới - REACTIVE
state.users = [...state.users, ...users];
Getters
getters handlers dùng để lấy dữ liệu từ state trong store.Ví dụ lấy một list users đã đăng ký (registered: true):
const store = createStore({
state: {
users: [
{ id: 1, name: '...', registered: true },
{ id: 2, name: '...', registered: false }
]
},
getters: {
registeredUsers: ({ state }) => {
return state.users.filter((user) => user.registered);
}
}
});
Getter handlers cung cấp một context object với store state. Không thể gọi actions khác từ getters.
Sử dụng Store
Cách sử dụng store sau khi tạo
Đầu tiên truyển store vào App instance:
// import our store
import store from 'path/to/store.js';
const app = new ZMP({
// truyền store cho tham số khởi tạo ứng dụng
store,
...
})
Truy xuất Store & State
Có thể truy xuất vào store thông qua instance của store đã tạo:
import store from 'path/to/store.js';
console.log(store.state.users);
Hoặc từ ZMP instance' store property:
import { zmp } from 'zmp-vue';
// ...
console.log(zmp.store.state.users);
Dispatching Actions
Để gọi một action cần gọi phương thức store.dispatch cùng tên của action.
Ví dụ có action getUsers:
const store = createStore({
// ...
actions: {
// nhận dữ liệu tuỳ chỉnh thông qua đối số thứ 2
getUsers({ state }, { total }) {
fetch(`some-url?total=${total}`)
.then((res) => res.json())
.then((users) => {
state.users = users;
});
}
}
// ...
});
Cần gọi phương thức store.dispatch:
import store from 'path/to/store.js';
// gọi 'getUsers' actions
store.dispatch('getUsers', { total: 10 });
Nếu muốn gọi action khác từ action handler:
const store = createStore({
// ...
actions: {
setLoading({ state }, isLoading) {
state.isLoading = isLoading;
},
// context object còn chứa phương thức "dispatch"
getUsers({ state, dispatch }, { total }) {
// gọi một action khác
dispatch('setLoading', true);
fetch(`some-url?total=${total}`)
.then((res) => res.json())
.then((users) => {
state.users = users;
// gọi action khác
dispatch('setLoading', false);
});
}
}
// ...
});
Getters
tạo các getters bằng cách định nghĩa tại store.getters.
const store = createStore({
state: {
count: 10
},
getters: {
count({ state }) {
return state.count;
},
double({ state }) {
return state.count * 2;
}
}
});
import store from 'path/to/store.js';
const count = store.getters.count;
const double = store.getters.double;
Getter value là một object với property .value cung cấp giá trị mà getter trả về, so:
console.log(count.value); // -> 10
console.log(double.value); // -> 20
Sử dụng với Vue Components
zmp-vue cung cấp useStore helper để sử dụng trong Vue components (tự động cập nhật components khi state/getters values thay đổi).
Vì useStore chỉ có thể sử dụng được bên trong setup()
function, bạn bắt buộc phải dùng phải dùng Composition API.
*useStore(getterName)- trả về getter value và theo dõi sự thay đổi của state*
- getterName - string - tên của getters handler
phương thức trả về getter value
Nếu muốn lấy getter value từ store instance khác:
*useStore(store, getterName)- trả về getter value và theo dõi sự thay đổi của state*
- store - store instance - Nếu bỏ trống mặc định sẽ là store của ứng dụng đã được truyề n vào
<App/>
. - getterName - string - tên của getters handler
phương thức trả về getter value
Ví dụ:
const store = createStore({
state: {
users: []
},
actions: {
getUsers({ state }) {
// ...
}
},
getters: {
users({ state }) {
return state.users;
}
}
});
Vue component:
<template>
<zmp-page>
<zmp-list>
<zmp-list-item v-for="user, index in users" :title="user.name" :key="index" />
</zmp-list>
</zmp-page>
</template>
<script setup>
import { onMounted } from 'vue';
import { useStore } from 'zmp-vue';
import store from '../store';
onMounted(() => {
store.dispatch('getUsers');
})
const users = useStore('users')
</script>
bởi vì sử dụng useStore helper/hook, component tự động cập nhật khi users tải xong.
Ví dụ
import { createStore } from 'zmp-core/lite';
const store = createStore({
state: {
loading: false,
users: []
},
actions: {
getUsers({ state }, { total }) {
state.loading = true;
setTimeout(() => {
state.users = [];
for (let i = 0; i < total; i++) {
state.users.push('User ' + (i + 1));
}
state.loading = false;
}, 3000);
}
},
getters: {
loading({ state }) {
return state.loading;
},
users({ state }) {
return state.users;
}
}
});
export default store;
<template>
<zmp-page>
<zmp-navbar back-link title="Store" />
<zmp-list v-if="users.length">
<zmp-list-item v-for="user in users" :title="user" :key="user" />
</zmp-list>
<zmp-card v-else inset>
<zmp-button fill preloader :loading="loading" @click="loadUsers">Load Users</zmp-button>
</zmp-card>
</zmp-page>
</template>
<script setup>
import { useStore } from 'zmp-vue';
import store from '../store';
const loading = useStore('loading')
const users = useStore('users')
const loadUsers = () => {
store.dispatch('getUsers', { total: 10 })
}
</script>