一、vuex
vuex 用全局单例的形式管理数据
vuex中的内容都在store实例里
vue component即view
state
vue component 中用store的state,把state放到组件的计算属性里,监听state变化做出响应的视图更新
// 在组件中用state
computed: {
count () {
return store.state.count
}
}
// 或
import { mapState } from 'vuex'
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
getter
getter是state的计算属性
// 在 vue component中使用getter
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
通过 mapGetters 访问
mutation
mutation 必须同步
在vue component 中用commit触发mutaion
在 action中用 commit触发mutation
const store = createStore({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
在组件中触发mutation
store.commit('increment')
或 用mapMutations
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
action
action可以异步可以同步
在vue component 中用dispatch触发action
// 在view中触发action
store.dispatch('xxx')
或 用mapActions
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
import { createStore } from 'vuex';
import http from '@/utils/http'
export interface IUserProps {
isLogin: boolean;
name?: string;
id?: string;
}
export interface IGlobalDataProps {
user: IUserProps;
token: string;
}
const store = createStore({
state(): IGlobalDataProps {
return {
user: {
isLogin: false,
name: '',
id: ''
},
token: localStorage.getItem('token') || ''
}
},
getters: {},
mutations: {
login(state: IGlobalDataProps, payload: any) {
console.log('mutations,,,,,,,login,,,,,,');
const token = payload.data.token;
state.token = token;
localStorage.setItem('token', token)
http.defaults.headers.common.Authorization = `Bearer ${token}`;
},
fetchCurrentUser(state: IGlobalDataProps, payload: any) {
console.log('mutations,,,,,,,fetchCurrentUser,,,,,,');
state.user = {
isLogin: true,
name: payload.data.nickName,
id: payload.data._id,
}
console.log('fetchCurrentUser mutations payload', payload)
},
logout(state: IGlobalDataProps) {
state.token = '';
localStorage.removeItem('token');
http.defaults.headers.common.Authorization = '';
}
},
actions: {
login(context, payload) {
console.log('actions,,,,,,,login,,,,,,');
return http.post('/user/login', payload)
.then(res => {
// TODO 如果code是其他的统一处理
if (res.data.code === 0) {
// 存储token
console.log('登录成功', res);
context.commit('login', res.data)
// return res.data;
}
}).catch(error => {
console.log('登录失败', error);
})
},
fetchCurrentUser(context) {
console.log('actions,,,,,,,fetchCurrentUser,,,,,,');
// 这么写就可以把异步执行完 在处理接下来的事件, 把then里的结果返回出去是promise(fullfilld)
return http.get('/user/current')
.then(res => {
if (res.data.code === 0) {
console.log('获取用户信息成功', res);
context.commit('fetchCurrentUser', res.data)
// return res.data;
}
}).catch(error => {
console.log('获取用户信息失败', error);
})
},
async loginAndFetchCurrentUser(context, payload) {
context.dispatch('login', payload).then(()=>{
context.dispatch('fetchCurrentUser');
});
}
}
})
export default store;
二、命名空间
目前是全局命名空间
默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间的——这样使得多个模块能够对同一个 action 或 mutation 作出响应。Getter 同样也默认注册在全局命名空间,但是目前这并非出于功能上的目的(仅仅是维持现状来避免非兼容性变更)。必须注意,不要在不同的、无命名空间的模块中定义两个相同的 getter 从而导致错误。
如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名