
getter相当于vuex里面的计算属性。

在vue组件中如果我们要触发一个全局的状态更新呢的话,中间其实还缺少一条线。如果我们的操作不具有异步操作的话,可以不走action,可以直接在vue组件中通过cmmitMutations来提交一个状态的改变。然后接着走下面的流程。

当我们在组件中需要自改vuex中的state状态值的时候,我们不可以在组件中直接修改这个值,而是需要commit提交一个mutation或者dispatch一个action,来走这么一个流程,这么看起来貌似很复杂和多余,这种操作是为了更清楚的帮我们梳理我们数据的改变,能够提供一个清晰的数据流,
实战
在mutations创建对象,然后把这个对象导出去。

index.js内引进来,然后创建实例的时候把他添加进去。

根级别的state有个appName

在这里我们使用了这个appName,它是一个计算属性,返回的是store中的appName

修改这个state的值,先在上面定义一个按钮


提示注册属性被指定了,但是它没有setter。


类似于这种get和set的写法,这只是做一个简单的示范

appName: { set: function (newValue) { this.inputValue = newValue + 'sd' }, get: function () { return this.inputValue + 'sdfsdf' } },
参数1就是通过那个方法名修改这个值

方法是在mutation中定义的。SET_APP_NAME

方法有个参数是state,就是同级别的state对象,

第二个参数vuex文档中叫做载荷,其实他就是参数值。如果是多个值的话params就是对象的形式,因为我们这里是一个值可以直接用params

commit的第一个参数就是我们要提交的名称

第二个参数就是要赋的新值

handleChangeAppName () { // this.appName = 'newAppName' this.$store.commit('SET_APP_NAME', 'newAppName') }

修改多个参数
这里就是一个对象的形式

handleChangeAppName () { // this.appName = 'newAppName' this.$store.commit('SET_APP_NAME', { appName: 'newAppName' }) }

const mutations = { SET_APP_NAME (state, params) { state.appName = params.appName } }

直接一个参数,对象的写法
type就是mutations内的名称

this.$store.commit({ type: 'SET_APP_NAME', appName: 'newAppName' })


params就是一个对象了 ,还是要通过params.appName

添加新的state值
想给state动态的添加appVersion这个属性

appVersion现在是没有的。后面想让他有这个值。

引入vue,使用vue的set方法,给state对象



然后使用这个appVersion



如果这里不用vue的set方法的话,直接修改state的appVersion属性

没有效果

说明在这里没有更新视图,这是vue中提到的响应式的原则,

如果一开始没有在state中定义,在创建实例的时候 是不会被添加get和set方法的,

那么视图就不会响应式的去更新。那么就需要使用vue.set把这个新的值添加到state对象上,同时它会给你添加get和set方法,同时会触发视图更新

mapMutations

注意:...mapMutations这个是methods里面定义的


这里改成直接用params


同时也可以写成对象的形式



模块中的mutation


上面新添加一个按钮



这里没有写模块名称,因为vuex会把模块中的和通用级别的,通通注册在全局当中,你只需要把它当做根级别的定义的get和mutation一样调用即可。

如果你想给他一个密闭的环境就设置namespaced

mutation中修改的值是通过接口获取的
获取接口中的操作呢,ajax请求是一个异步的操作。这个逻辑 是不能放在mutation中操作的。mutation只能做一些同步的操作。
如果有一些异步的操作 ,请求接口的数据再去修改state的值 怎么做?就会需要用到下面课要讲的action
Action


修改根级别的appName。这种写法是ES6的解构赋值

相当于这种写法,接收一个对象,然后获取对象中的commit

模拟一个异步的操作。假设getAppName是一个接口请求。

接口定义在api文件夹下的app.js

引用的简写形式

创建app.js

定义个promise对象,然后用settimeOut模拟一个http的延迟请求。

这里调用异步操作,打印这个结果看下


先注释掉

在这里提交一个action。先引入工具方法mapAction


调用这个方法


如果有catch就输出这个错误

提交修改appName

这里改成单个参数


还可以使用ES6的解构赋值

const { code, info: { appName } } = res commit('SET_APP_NAME', appName)
code没有用到这里就删掉

const { info: { appName } } = res commit('SET_APP_NAME', appName)
还可以使用store实例上的方法触发这个action,使用this.$store.dispatch(); 使用dispatch这个方法来触发action。参数载荷,可以以为对象 {}的形式,如果是一个值的话,就直接用'123'

这句话注释掉。

使用ES8的async来处理异步的问题。
这里使用了promise来处理逻辑。这种是类似于回调的形式。看起来并不是非常的友好

await等待一个异步函数执行,当它执行完成后,它会往下走,

async getAppName ({ commit }) { const { info: { appName } } = await getAppName() commit('SET_APP_NAME', appName) }

刚才方法名写错了


async处理异常 try catch的形式

async updateAppName ({ commit }) { try { const { info: { appName } } = await getAppName() commit('SET_APP_NAME', appName) } catch (error) { console.log(error) } }
module模块
当项目非常大的时候,store就会变的非常的臃肿,拆成模块管理比较清晰。每一个模块是一个独立的store
user下面还可以包含模块,拆分更细的模块。

如果user加上了命名空间那么这里调用的时候,也需要加上

如果模块里面套模块,这里就这么写

模块中用action


这种方式提交action

action中有另外的方法,可以在上面调用,用dispatch

store实例动态的注册一个模块。
动态的注册模块

第一个参数是模块名称,后面是一个对象,


注册一个todoList

如果有state.todo。那么就用state.todo.todoList.没有的话就是个空数组

todoList: state => state.todo ? state.todo.todoList : []
在上面做个循环


模块添加模块。给user模块添加一个子模块叫做todo


registerModule () { this.$store.registerModule(['user', 'todo'], { state: { todoList: [ '学习mutations', '学习actions' ] } }) }
把todo模块注册在user模块里 。

todoList: state => state.user.todo ? state.user.todo.todoList : []

结束