vuex入门

        在vue开发中,如果你的项目比较简单的话,在设计数据的状态、存储和操作的时候可以通过将数据存入到data中,通过eventBus的方式将数据发送出去,通过一堆methods来写关于这个操作的一些方法。但是如果到大型的项目开发中,如果通过这样子的方法去搞开发可以说不光打的代码多,而且代码的重用性非常的差,写代码会写的很繁琐。所以这个时候就应该用我们vue官方推荐的一个vuex来优化我们的模块设计。首先我们来看一下官方关于vuex的概念图:


        在这幅图中,state表示的是数据的存储状态,当你打开一个页面的时候,数据从后端获取并在浏览器那里加载完成后,一项关键的数据就会存入到state中,以供你以后操作的时候改变到state的变量时使视图发生相应的改变。components就是组件,components中通过vuex自带的一个mapGetters方法来获取state中相应的数据,从而渲染到components中,进而使整个视图层发生相应的改变。而actions就是对用户的操作进行反应,当用户点击一个按钮的时候,会触发这个按钮相应的方法,这个方法在actions中通过commit也就是提交,提交给mutaions让他去做处理,mutaions中通过在里面写业务的逻辑使得state中相应的对象属性发生改变,也只能有这条路才能让state发生改变,如果是通过对象的方式如用‘$store.state.属性=某个值‘来改变state的值都是非法的,官方不推荐,虽然可行,但是会乱了逻辑。接下来我就用一个简单的demo来实现上述的过程。

        在本次demo中,为了让新手简单了解起见,我没像官方那样用多个js文件来管理各个模块,我将整个vuex的流程都写入一个store.js的文件中。下面一个是能通过点击按钮进行流加减的程序流程。

        首先肯定是创建一个vue项目,用指令来初始化一个vue-cli:

vue init webpack haha
        然后安装后npm的依赖:

npm install
        然后运行看看有没有问题:

npm run dev
        没有问题后安装vuex:

npm install vuex
        我们在src目录下新建一个store.js文件,里面写关于我们的vuex逻辑的代码:


        在main.js中我们要把store.js文件import进来,然后挂着在new Vue中:

import Vue from 'vue'
import App from './App'
import store from './store'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  render: h => h(App)
})
        然后在store.js中引入vue和vuex,并且要在vue中使用vuex:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
        这个Vue.use()方法必不可少,因为vuex是插件,如果没有了这个方法去把vuex引入到vue中,则后面写的代码都无效。在这个store.js中,肯定会有我刚刚提到的state、actions、mutations和getters的,写法如下:

var state = {
  
}

const actions = {
  
}

const mutations = {
  
}

const getters = {
  
}
        通常state变量是页面一开始加载的时候通过ajax等异步方法获取到的后台数据就放在state中,getters就是将state里的某些属性给到components那里进行渲染,actions是用户点击一个按钮触发一个方法时就要经过这个actions,actions里面通过commit让mutaions执行相应的方法,只有mutations才能改state!然后这四个变量和常量要导出去,通过Vuex.Store来导出去:

export default new Vuex.Store({
  actions,
  getters,
  mutations,
  state
})
        在App.vue文件的template中,我是这样写的:

<template>
  <div id="app">
    <h3>简单计数器</h3>
    <button @click="increment">+1</button>
    <button @click="decrement">-1</button>
    <div>now is {{count}}</div>
  </div>
</template>
        这里有两个按钮,两个按钮对应着两个方法,一个是加1,另一个是减1,那么我们该如何实现呢?首先我们在下面的script中先引入vuex中的两个有用的方法:mapGetters和mapActions,这是vuex提供给我们的语法糖,通过你按照传统的方式写的话在methods里面写increment和decrement方法的实现,但是这里是vuex!这里有vuex自己的规则。在这里我们的methods是这样写的:

<script>
import {mapGetters, mapActions} from 'vuex'
export default {
  name: 'app',
  methods: mapActions([
    'increment',
    'decrement'
  ]),
  computed: mapGetters([
    'count'
  ])
}
</script>
        在mapActions中通过传入一个数组,里面有上面对应的两个方法名,传给store.js文件中进行处理。而我们想获取的参数count,通过计算属性computed里写入一个mapGetters方法,在该方法里传入count,就会在store.js方法里面进行处理,在store.js方法中通过getters返回该数值回来。下面我们就回到store.js,看看里面相应的变量和常量是如何写的。

        首先state里我们在里面设立一个属性,这个为count的原始值:

var state = {
  count: 10
}
        当用户点击按钮的时候,在actions中与之对应的方法就会commit该方法名给mutations,让mutations进行处理;

const actions = {
  increment: ({commit}) => {
    commit('increment')
  },
  decrement: ({commit}) => {
    commit('decrement')
  }
}

const mutations = {
  increment: (state) => {
    state.count++
  },
  decrement: (state) => {
    state.count--
  }
}
        最后,当App.vue组件想要获取count的数值的时候,需要在getters里面返回:

const getters = {
  count: (state) => {
    return state.count
  }
}
        题外话。有同学说我可以不用按照官方的来做,比如下面这样做也可以达到相应的效果:

<script>
// import {mapGetters, mapActions} from 'vuex'
export default {
  name: 'app',
//  methods: mapActions([
//    'increment',
//    'decrement'
//  ]),
//  computed: mapGetters([
//    'count'
//  ])
  data () {
    return {
      a: this.$store.state.count
    }
  },
  methods: {
    increment () {
      this.a += 1
    },
    decrement () {
      this.a -= 1
    }
  }
}
</script>
        在store.js文件中只需要state就可以了,看起来好像很简单啊。但是到需求量变的很大的时候,你这个方法无疑是搬起石头砸自己的脚。关键是这个不符合官方的规范!这个东西我已经在整篇文章提了三次,这个重要的东西值得说三次!

在官方那里除了我所提到的state、mutaions、actions、getters之外,还有一个modules。modules的功能就是分模块,在modules里面可以有state、mutaions、actions、getters,如果我们只是用那四个不用modules的话那么那四个相当于全局性的。在官方里modules的用法如下:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
        那么我们如何利用这个modules来改写我们刚刚写的代码呢?跟着我一步一步来。

const moduleA = {
  state: {
    count: 10
  },
  actions: {
    increment: ({commit}) => {
      commit('increment')
    },
    decrement: ({commit}) => {
      commit('decrement')
    }
  },
  mutations: {
    increment: (state) => {
      state.count++
    },
    decrement: (state) => {
      state.count--
    }
  },
  getters: {
    count: (state) => {
      return state.count
    }
  }
}
export default new Vuex.Store({
  modules: {
    a: moduleA
  }
})
        仿照官方那样,记住一定要export导出去,不然App.vue那里就不能import了。还要提的一点是,当你要执行异步操作的时候,是在actions里面进行的而不是在mutaions里面。如果在mutaions里面执行异步操作的话会使整个逻辑比较乱。具体更多的细节请参考官方文档。



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值