vuex作为vue的扩展,功能更加的强大,经过几天的摸索,我才逐步掌握,接下来给大家从头到尾详细分析一波:
首先我们安装vuex,我使用的是vue-cli脚手架工具进行配置使用:
1.基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //第一步 安装 vue init webpack vuex (拓展插件我只选择了路由【router】) npm install vuex --save //第二步 新建文件夹store,在里面新建index.js文件接下来引入 import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) //定义一个容器 let store = new Vuex.Store({}) export default store //第三步 在main.js中也要引入store文件 import store from "./store" |
2.对vuex的基本使用,使用vuex进行数据渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | //第一步 在store文件夹中的index.js中写上 表明我们定义的数字是100 let store = new Vuex.Store({ state:{ count:100 } //第二步 在视图对应的组件中我们使用vue中的计算属性对数据进行渲染 <template> <div> <h2>简易加法计算器</h2> <div> <input type="button" value="-" /> <span>{{num}}</span> <input type="button" value="+" /> </div> </div> </template> <script> export default { computed:{ num(){ //拿到vuex中的值 console.log(this.$store.state.count); return this.$store.state.count; } </script> //现在值是已经可以显示了,为100 |
3.添加事件,对数据可以进行加减操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | //第一步 在视图对应的组件中添加事件 <template> <div> <h2>简易加法计算器</h2> <div> <input type="button" value="-" @click="deHandle"/> <span>{{num}}</span> <input type="button" value="+" @click="addHandle"/> </div> </div> </template> <script> export default { computed:{ num(){ //拿到vuex的值 console.log(this.$store.state.count); return this.$store.state.count; }, }, methods:{ addHandle(){ //改变状态,提交mutation addIncrement会提交过去 ,下面的含义表示的是触发vuex中定义的事件addIncrement,mutation提交不应该有异步操作的数据 this.$store.commit("addIncrement") }, deHandle(){ this.$store.commit("deIncrement") } } } </script> //第二步 在store中的index.js中进行判定(有事件捕获的感觉) import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) //定义一个容器 let store = new Vuex.Store({ state:{ count:100 }, mutations:{ //state是一个默认的参数, addIncrement(state){ state.count+=1; }, deIncrement(state){ state.count-=1; } } }) export default store //到这里,一个使用vuex实现加减的效果就实现了 |
注意:
改变状态,提交mutation addIncrement会提交过去 ,下面的含义表示的是触发vuex中定义的事件
注意:以上为vue-cli2.0版本的,下面为3.0版本的,个人认为3.0的比2.0的要简单一些
简单的加减
1、编写组件,搭建路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | //router export default new Router({ //mode: 'history', //没有#模式 routes: [{ path: '/', name: 'data', component: data } ] }) //template <template> <div> <button @click="handleIncrement">增加</button> <input type="number" @change="changes" v-model="count"> <button @click="handleDecrease">减少</button> </div> </template> <script> export default { data () { return { } }, methods: { //监听数据的呀 changes () { console.log(1); }, handleIncrement () { this.$store.commit('increment'); }, handleDecrease () { this.$store.commit('decrease'); } }, computed: { count () { return this.$store.state.count } } } </script> //app.vue <template> <div id="app"> <router-link to="/">vuex数据展示</router-link> <router-view/> </div> </template> |
2、在store中的mutations编写代码实现加加减减的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | export default new Vuex.Store({ state: { count: 0 }, mutations: { //this.$store.commit('方法的名称','按需传入唯一的参数') increment(state) { state.count++ }, decrease(state) { state.count-- } }, getters: { //this.$store.getters.*** } }) |
3、在dada.vue组件中使用commit调用加减函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <template> <div> <button @click="handleIncrement">增加</button> <input type="number" @change="changes" v-model="count"> <button @click="handleDecrease">减少</button> </div> </template> <script> export default { data () { return { } }, methods: { //监听数据的呀 changes () { console.log(1); }, handleIncrement () { this.$store.commit('increment'); }, handleDecrease () { this.$store.commit('decrease'); } }, computed: { count () { return this.$store.state.count } } } </script> |
注意:使用this.$store.state.count可以直接在任何组件中获取到改属性的值
使用vuex获取数据进行过滤操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | //在store中定义数据为 list: export default new Vuex.Store({ state: { list: [1, 5, 8, 10, 30, 50] } } }) //在data.vue组件中定义 <template> <div> {{list}} </div> </template> <script> export default { data () { return { } }, methods: { }, computed: { list () { return this.$store.state.list.filter(item => item < 10); } } } </script> |
但问题在于,如果还有其他的组件也需要过滤后的数据时,就得把computed的代码完全复制一份,并且需要修改过滤方法时,每个用到的组件都得修改,如果能够将computed的方法也提取出来就方便很多了,getters就是用来做这个事的
使用getters来对数据进行筛选(filter)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | //在store中定义数据为 list: export default new Vuex.Store({ state: { list: [1, 5, 8, 10, 30, 50] }, getters: { //this.$store.getters.*** filteredList: state => { return state.list.filter(item => item < 10) } } } }) //在data.vue组件中定义 <template> <div> {{list}} </div> </template> <script> export default { data () { return { } }, methods: { }, computed: { list () { return this.$store.getters.filteredList; } } } </script> 这种用法与组件的计算属性非常的像。getter也可以依赖其他的getter,把getter作为第二次参数,比如在写一个getter,计算出list过滤后的结果的数量 |
这种用法与组件的计算属性非常的像。getter也可以依赖其他的getter,把getter作为第二次参数,比如在写一个getter,计算出list过滤后的结果的数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | //store中 getters: { //this.$store.getters.*** filteredList: state => { return state.list.filter(item => item < 10) }, listCount: (state, getters) => { return getters.filteredList.length; } } //data.vue中 <template> <div> {{list}} {{listCount }} </div> </template> <script> export default { data () { return { } }, methods: { }, computed: { list () { return this.$store.state.list.filter(item => item < 10); }, listCount () { return this.$store.getters.listCount; } } } </script> |
这里我们可以发现,传入的第二次参数getters其实就是当前的getters中包含的所有的方法
actions的使用
前言:mutation里不应该异步操作数据,所以有了actions选项。action与mutation很像,不同的是action里面提交的是mutation,并且可以异步操作业务逻辑。action在组件内通过$store.dispatch触发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //在store.js中 export default new Vuex.Store({ state: { count: 0, list: [1, 5, 8, 10, 30, 50] }, actions: { increment(context) { context.commit('increment'); } } }) //data.vue中 methods: { //监听数据的呀 changes () { console.log(1); }, handleIncrement () { this.$store.dispatch('increment'); } } |
感觉有点多次一举,因为可以直接通过mutation加以实现的呀,没必要通过action中转一次,但是加了异步就不一样了,我们用定时器在一秒后提交mutation,示例代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //store.js中的action中 asyncIncrement(context, callback) { setTimeout(() => { context.commit('increment'); callback() }, 1000) } //data.vue中 methods: { //handleAsyncIncrement 这个名字为点击事件名称,放置在+1的按钮上 handleAsyncIncrement () { this.$store.dispatch('asyncIncrement', () => { console.log(this.$store.state.count) }) } } |
mutations、actions看起来很相似,可能会觉得不知道该用哪个,但是Vuex很像是一种与开发者的约定,所以涉及改变数据的,就是用mutations,存在业务逻辑的,就用actions,至于将业务逻辑放在action里还是Vue组件里完成,就需要更具实际场景拿捏了。
Vuex最后一个知识点:modules
前言:modules用来将store分隔到不同的模块,当你的项目足够大的时候,store里面的state、getters、actions会非常多,都放在一个store.js中显得不太友好,所以写入到不同的文件中,每个module拥有自己的state、getters、actions、mutations,二期可以多层嵌套
曾经有一个面试者我问我一个问题,ajax请求方法你把它封装在vue哪里?
我说我有两个封装位置。
第一个是封装在全局混入中。
第二个是封装在vuex的util模块中。
你是如何封装的呢?