6.Vue技术栈开发实战-状态管理Vuex(二)



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

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

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

实战

在mutations创建对象,然后把这个对象导出去。

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

根级别的state有个appName

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


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



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

一个计算属性,默认情况下,它只有一个getter。是你在使用这个值的时候才会调取getter

类似于这种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里面定义的

 

 

 




注意上面调用SET_APP_NAME只传了一个参数,不是以对象的形式传递的,所以在mutations的方法里面,直接接收这个参数就可以了。不再是对象的形式。

这里改成直接用params



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




模块中的mutation

在user.js模块中定义一个mutations的方法

记得要把命名空间的选项关闭




上面新添加一个按钮






这里没有写模块名称,因为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'

这里因为我们的actions方法不需要参数,所以这里传递的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

 


registerModule () {
      this.$store.registerModule('todo', {
        state: {
          todoList: [
            '学习mutations',
            '学习actions'
          ]
        }
      })
    }
 

 


如果有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 : []

 


结束



 

posted @ 2020-05-20 09:11  高山-景行  阅读(256)  评论(0编辑  收藏  举报