Vuex: 在 Vue 项目中添加 vuex 的 store 支持
在 vue项目里,结合 nx 添加 store 的支持
cheatsheet
关键点 | 解释说明 |
store 可以被注入到 this.$store 中 |
|
actions 可以同步,可以异步 | - |
mutation 必须同步 | - |
不要直接改变 state,而是通过 dispatch操作 |
|
关注点
- App.vue: 有些人会将这个添加到 new Vue 中,这样可以在
this.$store
中调用到了 - store/index.js:
- store/modules/user.js: 具体的store 模块
src/shared/store/
├── index.js
└── modules
└── user.js
App.vue
,其实我并没有添加什么
import Vue from "vue";
import App from "./App";
import "./uni.promisify.adaptor";
import "./shared/bootstrap";
Vue.config.productionTip = false;
App.mpType = "app";
// start app
const app = new Vue({ ...App, store: nx.$store });
app.$mount();
store/index.js
: 管理 modules 里的多个 store,利用require.context
管理多个 store
import Vue from "vue";
import Vuex from "vuex";
const modulesFiles = require.context("./modules", true, /\.js$/);
// Auto import modules from modules folder
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, "$1");
const value = modulesFiles(modulePath);
modules[moduleName] = value.default;
return modules;
}, {});
Vue.use(Vuex);
nx.$store = new Vuex.Store({
modules,
});
store/modules/user.js
: 具体的 user 数据逻辑。
export default {
namespaced: true,
actions: {
async login({ commit }, data) {
commit('sets', { loading: true });
const res = await nx.$api.profile(data);
commit('sets', { loading: false, profile: res });
},
},
state() {
return {
loading: false,
profile: null
};
},
mutations: {
// common mutations
sets(state, data) {
nx.forIn(data, (key, value) => nx.set(state, key, value));
}
}
};
使用
# 调用 profile
nx.$store.dispatch('user/login')
# 取数据
nx.$store.state.user.profile
简化
简单封装,简化
API
的调用
nx.$store
: 真正的项目 store,与this.$store
指向同一个引用nx.$get
: 可以根据 path取得真正的state
里的值nx.$patch
: 相当于dispatch
nx.$mapStore
: 直接将 path 中的最后一段,映射为VueInstance
实际computed
中的值
// store
nx.$store = new Vuex.Store({
modules
});
// get
nx.$get = (inKey, inDefault) => {
const state = nx.$store.state;
if (!inKey) return state;
return nx.get(state, inKey, inDefault);
};
// dispatch(参考pinia的patch)
nx.$patch = (inPath, inPayload) => {
return nx.$store.dispatch(inPath, inPayload);
};
// mapState
// {
// loading: () => nx.$get('user.loading'),
// username: () => nx.$get('user.profile.login')
// },
nx.$mapState = (inKeys) => {
return inKeys.reduce((res, item) => {
const keys = item.split('.');
const lastKey = keys[keys.length - 1];
res[lastKey] = () => nx.$get(item);
return res;
}, {});
};
实际使用
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view>
<text>loading: {{ String(loading) }}</text>
<text class="title">{{ title }} - {{ login }}</text>
</view>
<button :disabled="loading" size="mini" type="primary" @click="handleClick">
点击
</button>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
};
},
computed: {
// user.profile.login -> login
// user.loading -> loading
// 其它语法糖: user.profile.login:username,即最后一个key,loading应该映射成为 username
...nx.$mapState(['user.profile.login', 'user.loading'])
},
onLoad() {},
methods: {
async handleClick() {
const res = await nx.$dispatch('user/login');
console.log('res: ', res);
}
}
};
</script>