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里面执行异步操作的话会使整个逻辑比较乱。具体更多的细节请参考官方文档。
- 上一篇: vue自定义全局组件(自定义插件)
- 下一篇: vue2.0之多页面的开发
