>>分享孙卫琴的Java技术专稿和著作 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 8307 个阅读者 刷新本主题
 * 贴子主题:  【Vue.js技术专题】Vuex中异步操作 回复文章 点赞(0)  收藏  
作者:sunweiqin    发表时间:2022-08-29 16:01:26     消息  查看  搜索  好友  邮件  复制  引用

本文参考孙卫琴,杜聚宾所创作的 <<精通Vue.js: Web前端开发技术详解>>一书

在仓库的actions选项的动作函数中,可以包含异步操作,例如以下actionA()动作函数会异步提交someMutation()更新函数:
actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

以下代码在一个组件的方法中派发actionA()动作函数:

this.$store.dispatch('actionA').then(() => {
  // 当actionA()动作函数中的异步操作执行完毕后,再执行then()函数指定的操作
  ……
})

在仓库的一个动作函数中还可以派发另一个动作函数:

actions: {
  //……
  actionB ({ dispatch, commit }) {  //actionB()函数派发actionA()函数
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

此外,还可以通过async/await来执行异步操作,例如

//假定getData()和getOtherData()返回Promise对象
actions: {
  async actionA ({ commit }) {  //async表明当前函数包含异步操作
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') //等待actionA()的异步操作执行完毕
    commit('gotOtherData', await getOtherData())
  }
}

1.异步动作范例

以下位于src/main.js中的代码创建了一个包含actions选项的仓库store,包括addQuantityAction()和calculateAction()动作函数:

const store = createStore({
  state () {
    return {
      item: {
        name: '苹果',
        price: 3.8,
        quantity: 1,
        total :  3.8
      }
    }
  },

  mutations: {
    addQuantity(state){  //增加购买数量
      state.item.quantity++
    },
    calculate(state){  //计算总价格
     state.item.total=state.item.price * state.item.quantity
    }
  },

  actions: {
    addQuantityAction({commit}){
      return new Promise((resolve)=>{
        setTimeout(          //模拟异步操作
          ()=>{
             commit('addQuantity')
             resolve()
          },2000)
      })
    },

    calculateAction({commit,dispatch}){
      //等购买数量增加后,再计算总价格
      dispatch('addQuantityAction').then( ()=>{
        commit('calculate')
      })
    }
  }
})

以上代码中的动作函数的作用如下:
(1)addQuantityAction()动作函数:包含异步操作,过2秒后提交addQuantity()更新函数。
(2)calculateAction()动作函数:会派发addQuantityAction()动作函数,等到addQuantityAction()动作函数的异步操作执行完毕以后,再执行then()函数,从而提交calculate()更新函数。
例程1的AsyncJudge.vue定义了AsyncJudge组件,它的calculate()方法会向仓库派发calculateAction()动作函数。

例程1  AsyncJudge.vue

<template>
  <div>
    <p>商品名字: {{item.name}}  </p>
    <p>单价: {{item.price}}  </p>
    <p>数量: {{item.quantity}}  
    <button @click="calculate">增加</button>  </p>
    <p>总价:{{item.total}}</p>
  </div>
</template>
  
<script>
  import { mapState,mapActions } from 'vuex'

  export default {
    computed: mapState(['item']),
  
    methods: {
      ...mapActions({calculate: 'calculateAction'})  
    }
  }
</script>

在src/router/index.js中,为AsyncJudge组件设置的路由的路径为“judge”。通过浏览器访问“http://localhost:8080/#/judge”,会出现如图1所示的网页。在网页上点击“增加”按钮,就会看到在延迟2秒后,{{item.quantity}}以及{{item.total}}的取值会发生相应的更新。
点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小  
图1  AsyncJudge组件的页面

2.  使用async/await的范例

以下位于src/main.js中的代码创建了一个包含actions选项的仓库store,包括一个loadCustomerAction()动作函数,该动作函数用async来标识,表明是包含异步操作的函数:

const store = createStore({
  state () {
    return {
      customer: '',
      msg: ''
    }
  },

  mutations: {
    clearCustomer(state){
      state.msg='正在查询...'
      state.customer=''
    },
    loadCustomer(state,response){
      if(response.data !== null){
        state.customer=response.data
        state.msg=''
      }else
        state.msg='未找到匹配的数据!'    
    }
  },

  actions: {
    async loadCustomerAction({commit},id){
      commit('clearCustomer')  
      const response=await axios({
         baseURL: 'http://www.javathinker.net',
         url: '/customer',
         method: 'get',
         params: {id: id}
      })
      commit('loadCustomer',response)
    }
  }
})

loadCustomerAction()动作函数会通过Axios请求访问服务器,查询与id匹配的customer对象。在异步调用axios()函数之前,会提交clearCustomer()更新函数,等到Axios的异步请求执行完毕,再提交loadCustomer()更新函数。

例程2的AsyncCustomer.vue定义了AsyncCustomer组件。它的getCustomer()方法会向仓库派发loadCustomerAction()动作函数。

例程2  AsyncCustomer.vue

<template>
  <div>
    <p>输入id: <input v-model="id" />  
           <button @click="getCustomer">查询</button>  {{msg}}
    </p>  
    <p>{{customer}}</p>
  </div>
</template>
  
<script>
  import {mapState} from 'vuex'
  export default {
    data(){ return {id: '' }},
    computed: mapState(['customer','msg']),
    methods: {
      getCustomer(){
        this.$store.dispatch('loadCustomerAction',this.id).then(
          ()=>{console.log(this.customer)}
        )
      }
    }
  }
</script>

在src/router/index.js中,为AsyncCustomer组件设置的路由的路径为“cust”。通过浏览器访问“http: //localhost:8080/#/cust”,会出现如图2所示的网页。在网页上的id输入框输入1,再点击“查询”按钮,会看到网页先显示“正在查询...”,延迟一段时间后,再显示id为1的customer对象的信息。
点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小
图2  AsyncCustomer组件的页面




程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->内部类
  JavaWeb开发-->JSP技术详解(Ⅰ)
  JSP与Hibernate开发-->映射一对多关联关系
  Java网络编程-->用Spring整合CXF发布Web服务
  精通Spring-->虚拟DOM和render()函数
  Vue3开发-->通过Vuex进行状态管理
  【Vue.js技术专题】路由导航中抓取数据
  【Vue.js技术专题】分割setup()函数
  【Vue.js技术专题】在Vue项目中使用Axios
  【Spring Cloud Alibaba专题】GateWay与Nacos整合
  【Java基础编程专题】使用和创建JavaDoc文档
  向小伙伴们推荐我所创作前后端编程书籍的学习顺序
  【持久化专题】为什么JPA和Hibernate的持久化方法都抛出运行...
  【Spring专题】服务器端推送
  【持久化专题】映射对象标识符的基本原理
  【持久化专题】用@MapsId注解映射派生主键
  【持久化专题】JPA API的基本用法
  【持久化专题】对象-关系的映射概念
  【Java网络编程专题】异步通道和异步运算结果
  【Java基础编程专题】为什么说:继承关系最大的弱点就是打破...
  我的计算机书籍创作心得
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。