Vuex的简单使用

(注:以下所有截图均来自我的微信公众号“生锈的TRUENO”,欢迎各位关注~)   

Vuex是一个专为Vue.js应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

    每个Vue组件都由三个基本的部分组成:state,view,actions:

    其中,state是驱动应用的数据源,view以声明的方式将state映射到视图,actions用来响应在view上的用户输入导致的状态变化。具体到一个简单的Vue组件中,state可以指组件的script中的data,view可以指组件的template中对data里数据的绑定和使用,actions则可以指组件的template中对于组件的script中方法的绑定。

    简单地说,上述Vue组件中的三个部分完成了从数据到视图的渲染,再到用户操作视图从而修改数据这一“单向数据流”。组件的状态随着数据流的不断运动而不断改变。

    这么看来,貌似单个Vue组件就可以完成状态的管理,那为什么还需要Vuex呢?我们来举个栗子:

    一个购物车应用,当用户将想要的物品添加到购物车后,需要点击付款,从而跳转到另外一个页面,而这个付款页面除了填写地址等信息外,肯定还要有用户刚刚选中的商品信息,也就是购物车中的数据。这个简单的需求涉及到了一个问题:数据的跨页面传递。

    我们可以想一下一般来说如何实现数据的跨页面传递。1.可以把当前页面需要传递的数据放到url里,在页面跳转的同时,就把数据传递到新的页面了;2.还可以把数据放到cookie里,利用浏览器缓存,让新的页面调用cookie中的数据,从而实现数据的传递;3.利用数据库,在一个页面中修改数据后,先将数据存到数据库,然后在另一个页面中,从数据库中对该数据进行读取。总而言之,上述的方法都需要一个媒介,把数据传来传去,这会增加系统的不可维护性。

    因此,Vuex为我们提供了一个统一管理多个组件共享的数据的方式,我们只需要对一组共享数据进行维护,然后共享这些数据的所有组件都可以对这些数据进行使用和修改,这就大大提升了系统的可维护性。

    下面,举一个简单的栗子来说明Vuex的使用方法和效果:

    需求:写一个简单的购物车功能,一共两个页面,一个是购物车页面,用来确定商品的数目,另一个是计数页面,用来显示当前购物车中的商品总数。最终要实现在购物车页面修改后的商品数目,可以和计数页面显示的商品总数一致的效果。

    先看一下应用的目录结构:

 

是我用vue-cli搭建的一个项目,这个目录只显示了主要的部分,其中“components”中的两个组件分别是计数组件和购物车组件,router中的index.js用于设置前端路由,store是Vuex的核心代码,main.js是项目的入口文件。

    为了使用Vuex,需要在入口文件main.js中引入,main.js代码如下:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'//引入vuex

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,//引入vuex
  components: { App },
  template: '<App/>'
})

   store是Vuex的核心代码,首先来看一下state.js,该文件用来定义共享数据:


/*
状态对象
*/
export default{
    totalNum:0//商品总数
}

    state只是实现了共享数据的定义,它可以让Vue组件使用共享数据,但是如果组件需要修改共享数据,那就要用到mutation.js:


/*
直接更新state的多个方法的对象
*/
export default{
    changeNum(state,currentNum){
        state.totalNum  = currentNum
    }
}

    在Vuex中,mutation是唯一可以修改共享数据的入口,即任何对共享数据的修改操作都要通过mutation。

    我们可以看到在store中,还有一个getters.js和actions.js,其中getters用来从state中的原始数据进一步派生出新的数据,因为有时往往组件需要的是经过进一步处理的派生数据,而action则用来处理异步请求,因为mutation只能用来处理同步请求,但是有些数据,比如商品列表,是通过调用后端接口获得的,因此是异步的,只有数据获得到才可以修改state中的值,所以,Vuex使用action处理异步请求,action并不直接处理state中的数据,而是在回调函数中,提交mutation,这样就能保证先获得数据,再修改state。而在本次示例中, 并没有用到getter和action,因此暂且不展示这两个的使用。

    最后,store需要一个index.js将上述文件组织起来:

/*
vuex最核心的管理对象
*/
import Vue from 'vue';
import Vuex from 'vuex';
import state from './state';
import mutations from './mutations';
import actions from './actions';
import getters from './getters';

Vue.use(Vuex)

export default new Vuex.Store({
    state,
    mutations,
    actions,
    getters,
})

    我们再来看看两个Vue组件,首先是计数组件count.vue:


<template>
    <div>
        <div>当前购物车中总的商品数为:{{totalNum}}</div>
        <router-link to="/">返回购物车界面</router-link>  
    </div>
</template>

<script>
import {mapState} from 'vuex'
export default {
    name: 'count',
    data() {
        return {
            
        }
    },
    computed:{
    ...mapState(['totalNum'])
  },
}
</script>

<style scoped>
</style>

    我们看到该组件需要用到共享数据“totalNum”,因此,需要先在script中引入mapState,然后在computed中使用mapState并选中totalNum,这样,totalNum就和组件中的data一样,可以直接使用了。

    我们再来看看购物车组件shoppingCar.vue:


<template>
  <div class="hello">
    <div>
      {{msg}}
    </div>
    <br>
    <br>
    <span>
      <input type="text" :value="totalNum"/>
      <button @click="increaseNum">+</button>
      <button @click="decreaseNum">-</button>
    </span>
    <router-link to="/count">查看当前总商品数</router-link> 
  </div>
</template>

<script>
import {mapState,mapMutations} from 'vuex'
export default {
  name: 'shopping',
  data () {
    return {
      msg: '欢迎来到购物车界面',
    }
  },
  computed:{
    ...mapState(['totalNum'])
  },
  methods:{
    ...mapMutations(['changeNum']),
    increaseNum(){
      this.changeNum(this.totalNum+1);
    },
    decreaseNum(){
      this.changeNum(this.totalNum-1);
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

    可以发现,该组件同样需要用到“totalNum”这个共享数据,与此同时,该组件还需要对这个共享数据进行修改,而修改共享数据,则还需要引入“mapMutations”,并在script的methods中,使用mapMutations选中mutation中的方法“changeNum”,此后,这个方法就和vue组件中其他的method一样了,可以在视图中直接用@click进行绑定。

    从整体来看Vuex的工作机制如下图所示:

    好,我们来看一下运行效果,首先在购物车页面修改商品数:

然后,点击“查看当前商品总数”,进入计数界面:

可以发现:数目和购物车页面中修改的结果一致,并且URL并没有传递参数,代码中也没有使用cookie和数据库,只需要正确使用Vuex就实现了跨页面数据传递。随着项目的扩大,这一效果将会变得十分方便,且容易维护!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值