到这里就可以使用Vuex编写业务了但是如果你想写的再好一点强烈看一下本文
我们看一下index.js
store > index.js
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
const actions = {
//这俩个好像与求和有关
jia(context,value){
context.mutations('JIA',value)
},
jian(context,value){
context.mutations('JIAN',value)
},
}
const mutations = {
//这里有三个mutations
//JIA和JIAN服务于求和,但是ADD_PERSON服务于Person组件
JIA(state,value){
state.sum += value
},
JIAN(state,value){
state.sum -= value
},
ADD_PERSON(state,value){
state.personList.unshift(value)
}
}
const state = {
sum:0,
school:'bilibili',
subject: 'Vue',
personList:[
{id:'001',name:'张三'}
]
}
//准备getters:用于将state中的数据进行加工
const getters = {
//给你要实现运算的值取一个名字
bigSum(state){ //能接收到state的值
return state.sum*10//跟计算属性类似:靠返回值来决定自己的值
}
}
export default new Vuex.Store({
actions,mutations,state,
getters
})
在mutations
里如果业务一旦多起来,都写在mutations
会很凌乱,而且难以维护。 我们的目的是把不同分类的mutations
放在不同的位置:
store > index.js
//求和功能相关的配置
const countOptions = {
actions:{},
mutations:{},
state:{},
getters:{},
}
//人员管理功能相关的配置
const PersonOptions = {
actions:{},
mutations:{},
state:{},
getters:{},
}
把配置放入:
//求和功能相关的配置
const countOptions = {
actions:{
jia(context,value){
context.mutations('JIA',value)
},
jian(context,value){
context.mutations('JIAN',value)
},
},
mutations:{
JIA(state,value){
state.sum += value
},
JIAN(state,value){
state.sum -= value
},
},
state:{
sum:0,
school:'bilibili',
subject: 'Vue',
},
getters:{
//给你要实现运算的值取一个名字
bigSum(state){ //能接收到state的值
return state.sum*10//跟计算属性类似:靠返回值来决定自己的值
}
},
}
//人员管理功能相关的配置
const PersonOptions = {
actions:{},
mutations:{
ADD_PERSON(state,value){
state.personList.unshift(value)
}
},
state:{
personList:[
{id:'001',name:'张三'}
]
},
getters:{},
}
这样里面没有actions,mutations,state,getters
这么一些
怎么使用:
export default new Vuex.Store({
modules:{//模块的复数
//这么写的含义就是Store里面所保存的东西都开始分类了
a:countOptions,
b:PersonOptions
}
})
原来的Vuex.Store
里面:
Store -> Actions
-> Mutations
-> State
-> getters
模块化编码后就是:
store -> a(分类名自己取) ->Actions
->Mutations
->State
->getters
-> b(分类名自己取) ->Actions
->Mutations
->State
->getters
*可以触发对象的简写形式
因为这样要访问得写$store.a.state.sum
形式,所以就先不用简写形式
App.vue
借助mapState
生成的personList
...mapState(['sum','personList']),
里面用到的都得是在store
里面有的东西
看看store
里面到底长啥样:
mountde(){
console.log(this.$store)
}
Store {_committing: false, _actions: {…}, _actionSubscribers: Array(1), _mutations: {…}, _wrappedGetters: {…}, …}
commit: ƒ boundCommit(type, payload, options)
length: 3
name: "boundCommit"
prototype: {constructor: ƒ}
arguments: (...)
caller: (...)
[[FunctionLocation]]: vuex.esm.js?2f62:408
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[4]
dispatch: ƒ boundDispatch(type, payload)
length: 2
name: "boundDispatch"
prototype: {constructor: ƒ}
arguments: (...)
caller: (...)
[[FunctionLocation]]: vuex.esm.js?2f62:405
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[4]
getters:
bigSum: (...)
get bigSum: ƒ ()
[[Prototype]]: Object
registerModule: (e,t,r)=> {…}
replaceState: e=>{l.initialState=A(e),t(e)}
strict: false
unregisterModule: e=> {…}
_actionSubscribers: (2) [{…}, {…}]
_actions: {jia: Array(1), jian: Array(1)}
_committing: false
_devtoolHook: {enabled: undefined, _buffer: Array(0), store: Store, initialState: {…}, Vue: ƒ, …}
_makeLocalGettersCache: {}
_modules: ModuleCollection {root: Module}
_modulesNamespaceMap: {}
_mutations: {JIA: Array(1), JIAN: Array(1), ADD_PERSON: Array(1)}
_subscribers: [ƒ]
_vm: Vue {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_watcherVM: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_wrappedGetters: {bigSum: ƒ}
state: Object
a: Object
school: (...)
subject: (...)
sum: (...)
__ob__: Observer {value: {…}, dep: Dep, vmCount: 0}
get school: ƒ reactiveGetter()
set school: ƒ reactiveSetter(newVal)
get subject: ƒ reactiveGetter()
set subject: ƒ reactiveSetter(newVal)
get sum: ƒ reactiveGetter()
set sum: ƒ reactiveSetter(newVal)
[[Prototype]]: Object
b: Object
personList: (...)
__ob__: Observer {value: {…}, dep: Dep, vmCount: 0}
get personList: ƒ reactiveGetter()
set personList: ƒ reactiveSetter(newVal)
[[Prototype]]: Object
__ob__: Observer {value: {…}, dep: Dep, vmCount: 0}
get a: ƒ reactiveGetter()
set a: ƒ reactiveSetter(newVal)
get b: ƒ reactiveGetter()
set b: ƒ reactiveSetter(newVal)
[[Prototype]]: Object
[[Prototype]]: Object
看state
里面的。所以说知道怎么修改了(先修改state):
当前的值为:{{a.sum}}
当前的值*10为:{{bigSum}}
Person组件的总人数有:{{b.personList.lenght}}
那能不能像之前那样写?
是可以的
...mapState('a',['sum']),
这样写会报一个错误:
[vuex] module namespace not found in mapState(): a/
模块的名字空间没有找到在mapsState里面:a
module:模块
namespace:名字空间
not found:没有找到
你如果想在mapState里面通过第一个参数去指定分类。你想这么写,你得有个前提:在配置Vuex的时候在配置里面加上一个配置项:namespaced
const countOptions = {
namespaced: true,
actions:{
jia(context,value){
context.mutations('JIA',value)
},
jian(context,value){
context.mutations('JIAN',value)
},
},
mutations:{
JIA(state,value){
state.sum += value
},
JIAN(state,value){
state.sum -= value
},
},
state:{
sum:0,
school:'bilibili',
subject: 'Vue',
},
getters:{
//给你要实现运算的值取一个名字
bigSum(state){ //能接收到state的值
return state.sum*10//跟计算属性类似:靠返回值来决定自己的值
}
},
}
如果不写默认为false
。你只有写了,你这个a
才能被mapState
里面所认识
所有的简写都是有代价的
store > index.js
//人员管理功能相关的配置
const PersonOptions = {
namespaced: true,
actions:{},
mutations:{
ADD_PERSON(state,value){
state.personList.unshift(value)
}
},
state:{
personList:[
{id:'001',name:'张三'}
]
},
getters:{},
}
App.vue
computed:{
...mapState('a',['sum']),
...mapState('b',['personList']),
...mapGetters(['bigSum'])
},
但是一点+
:
[vuex] unknown mutation type: JIA
你没说明白,所以还是上面的操作:
methods:{
...mapMutations('a',['JIA','JIAN']),
},
Actions
谁的Mutations
谁的State
谁的getters
[vuex] unknown getter: bigSum
同理:
...mapGetters('a',['bigSum'])
结合上面我们去修改person.vue
里的求和
查看this.$store
Store {_committing: false, _actions: {…}, _actionSubscribers: Array(1), _mutations: {…}, _wrappedGetters: {…}, …}
commit: ƒ boundCommit(type, payload, options)
dispatch: ƒ boundDispatch(type, payload)
getters: {}
registerModule: (e,t,r)=> {…}
replaceState: e=>{l.initialState=A(e),t(e)}
strict: false
unregisterModule: e=> {…}
_actionSubscribers: (2) [{…}, {…}]
_actions: {a/jia: Array(1), a/jian: Array(1)}
_committing: false
_devtoolHook: {enabled: undefined, _buffer: Array(0), store: Store, initialState: {…}, Vue: ƒ, …}
_makeLocalGettersCache: {a/: {…}, b/: {…}}
_modules: ModuleCollection {root: Module}
_modulesNamespaceMap: {a/: Module, b/: Module}
_mutations: {a/JIA: Array(1), a/JIAN: Array(1), b/ADD_PERSON: Array(1)}
_subscribers: [ƒ]
_vm: Vue {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_watcherVM: Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
_wrappedGetters: {a/bigSum: ƒ}
state: Object
a: (...)
b: (...)
state
里面只有a
和b
所以这么改:
computed:{
personList(){
return this.$store.state.b.personList
},
sum(){
return this.$store.state.a.sum
}
}
点击添加,控制台报错:
[vuex] unknown mutation type: ADD_PERSON
this.$store.commit('b','ADD_PERSON',personObj)
你觉得这样可以,但是:
[vuex] unknown mutation type: b
也就是它不支持这个写法,得这么写:
methods:{
add(){
//id可以用nanoid生成
const personObj = {id: nanoid(),name: this.name}
this.$store.commit('b/ADD_PERSON',personObj)
this.name = ''//清空输入框
}
},
store > index.js
actions:{
addPersonWang(context,value){
if(value.name.indexOf('王') === 0){
context.commit('ADD_PERSON',value)
}
}
},
Person.vue
<button @click="addWang">添加一个姓王的人button>
错误写法:
addWang(){
const personObj = {id:nanoid(),name: this.name}
this.$store.dispatch('addPersonWang',personObj)
this.name = ''
}
报的错:
[vuex] unknown action type: addPersonWang
你就知道怎么写了:
addWang(){
const personObj = {id:nanoid(),name: this.name}
this.$store.dispatch('b/addPersonWang',personObj)
this.name = ''
}
输入李四
没添加进去,但是这不太好(提示):
actions:{
addPersonWang(context,value){
if(value.name.indexOf('王') === 0){
context.commit('ADD_PERSON',value)
}else{
alert('添加的人必须姓王')
}
}
},
getters:{
fristPersonName(state){//这个state拿到的只是自己的state,不是全部的state
return state.personList[0].name
}
},
computed:{
personList(){
return this.$store.state.b.personList
},
sum(){
return this.$store.state.a.sum
},
fristPersonName(){
return this.$store.getters.b.fristPersonName
}
}
控制台出现:
[Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'fristPersonName')"
说明你在getters
里那不到b
。
Store {_committing: false, _actions: {…}, _actionSubscribers: Array(1), _mutations: {…}, _wrappedGetters: {…}, …}
commit: ƒ boundCommit(type, payload, options)
dispatch: ƒ boundDispatch(type, payload)
getters:
a/bigSum: (...)
b/fristPersonName: (...)
get a/bigSum: ƒ ()
get b/fristPersonName: ƒ ()
[[Prototype]]: Object
getters
的分类与state
里的分类有所不同
所以得这么取:
fristPersonName(){
return this.$store.getters.b/fristPersonName.fristPersonName
}
但是你这么写不行啊。有.
和/
。所以得这么写:
fristPersonName(){
return this.$store.getters['b/fristPersonName']
}
如果a中有一个user
但是b中也有一个user属性
它俩一点也不冲突。解决命名冲突问题
而且a和b中的countOptions
和PersonOptions
也不是非得写在一起:
store > 创建
count.js
//求和功能相关的配置
export default{
namespaced: true,
actions:{
jia(context,value){
context.mutations('JIA',value)
},
jian(context,value){
context.mutations('JIAN',value)
},
},
mutations:{
JIA(state,value){
state.sum += value
},
JIAN(state,value){
state.sum -= value
},
},
state:{
sum:0,
school:'bilibili',
subject: 'Vue',
},
getters:{
//给你要实现运算的值取一个名字
bigSum(state){ //能接收到state的值
return state.sum*10//跟计算属性类似:靠返回值来决定自己的值
}
},
}
store > 创建
person.js
//人员管理功能相关的配置
export default{
namespaced: true,
actions:{
addPersonWang(context,value){
if(value.name.indexOf('王') === 0){
context.commit('ADD_PERSON',value)
}else{
alert('添加的人必须姓王')
}
}
},
mutations:{
ADD_PERSON(state,value){
state.personList.unshift(value)
}
},
state:{
personList:[
{id:'001',name:'张三'}
]
},
getters:{
fristPersonName(state){//这个state拿到的只是自己的state,不是全部的state
return state.personList[0].name
}
},
}
store > index.js
import Vuex from 'vuex'
import Vue from 'vue'
import countOptions from './count'
import PersonOptions from './person'
Vue.use(Vuex)
export default new Vuex.Store({
modules:{//模块的复数
//这么写的含义就是Store里面所保存的东西都开始分类了
a:countOptions,
b:PersonOptions
}
})
store > person.js
import axios from 'axios'//引入axios
addPersonForServer(context){
axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
response=>{
console.log('成功了',response.data)
context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
},
error=>{
console.log('报错了,信是:',error.message)
}
)
}
person.vue
<button @click="addPersonServer">添加一个人,名字随机button>
addPersonServer(){
this.$store.dispatch('b/addPersonForServer')
}
1.目的: 让代码更好维护,让多种分类更加明确。
2.store > index.js
开启命名空间:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)//使用Vuex插件
const name1 = {
namespaced: true,
actions:{...},
mutations:{...},
state:{...},
getters:{...}
}
const name2 = {
namespaced: true,
actions:{...},
mutations:{...},
state:{...},
getters:{...}
}
...
export default new Vuex.Store({
modules:{
a:name1,
b:name2
}
})
3.开启命名空间后,组件读取state数据:
//方式一: 自己直接读取
this.$store.state.a.list
//方式二: 借助mapState读取
...mapState('a',['sum'])
4.开启命名空间后,组件中读取getters数据
//方式一: 自己直接读取
this.$store.getters[a/方法名]
//方式二: 借助mapGetters读取
...mapGetters('a',['bigSum'])
5.开启命名空间后,组件中读取dispatch
//方式一: 自己直接读取
this.$store.dispatch('a/方法名',value)
//方式二: 借助mapActions读取
...mapActions('a',{add:'sum',jian:'jian'})
6.开启命名空间后,组件中调用commit
//方式一: 自己直接commit
this.$store.commit('a/方法名',value)
//方式二: 借助mapMutations:
...mapMutations('a',{add:'JIA',jian:'JIAN'})
(重点中的重点)网络请求传数据