博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vuex 学习记录
阅读量:6077 次
发布时间:2019-06-20

本文共 8378 字,大约阅读时间需要 27 分钟。

vuex

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

vueX有几个核心的概念:

  • State

  • Getters

  • Mutations

  • Actions

  • Modules

首先我们用vue-cli构建一个vue目录,如图所示

clipboard.png]

其中有三个vue组件,app.vue,hello.vue,content.vue,在router目录的index.js定义了路由关系。

import Vue from 'vue'    import Router from 'vue-router'    import Hello from '@/components/Hello'        Vue.use(Router);            export default new Router({      routes: [        {          path: '/',          name: 'Hello',          component: Hello        }      ]    })

APP.vue

hello.vue

content.vue

通过上面的三个组件和路由我们可以看出,访问跟路径,app组件引入hello组件,hello.vue嵌套content.vue组件,跟main.js同级建一个store.js,定义vuex的store和简单的mutations

import vue from 'vue';  import vuex from 'vuex';      vue.use(vuex);      export default new vuex.Store({    state:{       time:new Data().getTime(),       names:["张三"],    }  })

修改main.js,添加vuex的使用

import Vue from 'vue'           import App from './App'           import router from './router'           import store from './store.js'                           new Vue({             el: '#app',             router,             store,             template: '
', components: { App } });

这个时候这个项目已经把 store 的实例注入所有的子组件,里面有一个state对象和mutations对象,state包括了全部的状态,作为一个唯一数据源存在,vue项目里面可以在任意组件里面引用state里面的属性,

如何在vue组件引入state,几种常用的办法

  1. 通过 js {

    { this.$store.state.time }} 可以直接访问store定义的state对象

  2. 计算属性中返回某个状态

    computed:{   count(){return this.$store.state.time;   } }
  3. 当一个组件获取多个状态,上面两种使用方式比较重复和冗余,为了解决这个问题,我们可以使用mapState辅助函数

    import {mapState} from 'vuex'         export default {          computed:mapState([  'time'     ])      }
  • mapState返回一个对象,映射this.count为this.$store.state.time,mapState里面参数是数组形式,参数名和state同名

    import {mapState} from 'vuex'computed:mapState({   time:state=>state.time,   nameArr:'names'})
  • 这种方式的mapState形参是一个对象,第一个count使用箭头函数,返回state.count,第二个修改了names的别名变成nameArr

Mutations

我们修改store.js,通过添加mutations,来改变store里面的state。更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数

export default new vuex.Store({     state:{       time:new Date().getTime(),       names:["张三"]     },     mutations:{       pushName (state,thisName){         state.names.push(thisName.name)       }     }   })

我们修改app组件,

  

姓名: {

{ name }}   

export default {        name: 'app',        data(){            return {              msg: 'Welcome to Your App.vue components',              addName:''            }        },        computed:mapState({              nameArr:'names'        }),        methods:{            addNameFn(){                var that=this;                this.$store.commit('pushName',{name:that.addName})                           }                  }      }

Mutations必须是同步函数,因为每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而 mutation 在异步函数中的回调让这不可能完成

调用方式有三种

  1. 使用this.$store.commit调用,第一个参数是Mutations里面定义的方法名,第二个参数是传入的形参,建议应该是一个对象,可以包含多个字段,并且会更容易阅读代码

    addNameFn(){ this.$store.commit('pushName',{  name:this.addName })  }
  2. 使用 type属性对象,commit调用的参数只有一个是一个对象,type是Mutations里面定义的方法名,其他字段是形参

    addNameFn(){ this.$store.commit({   type:'pushName',   name:this.addName })   }
  3. 使用mapMutations,引入 mapMutations ,将methods 映射为 store.commit 调用

    import {mapMutations} from 'vuex'     methods:{  ...mapMutations([      'pushName'  ]),     addNameFn(){    this.pushName({name:that.addName})  }   }

Getters

有时候我们需要根据store中的state中的属性派生一些值,例如统计添加的姓名总数,如果有多个组件需要用到统计姓名总数这个值,我们要么是在每个组件中重复写一个方法,要么是

写一个公用的方法,每个组件引入,这两种方法都不是很理想,所以引入了Getters,可以认为是store的计算属性,首先添加getters,添加一个统计添加的姓名总数的方法,并且在每个组件打印这个总数

修改store.js,添加getters属性,添加getNameLen方法,参数是state

export default new vuex.Store({     state:{       time:new Date().getTime(),       names:["张三"]     },     mutations:{       pushName (state,thisName){         state.names.push(thisName.name)       }     },     getters:{       getNameLen:state=>{         return state.names.length       }     }   })

修改App.vue的template,直接打印添加姓名的个数

    

姓名: {

{ name }}   

人数:{

{ this.$store.getters.getNameLen }}

修改完这些,我们发现当我们添加一个姓名,每个组件都会更新添加的姓名的总条数,getters调用就是这么简单,上面只是一种调用方式,除此外还有两种调用方式

1.在计算属性中引入

人数:{

{ getNameLen }}

computed: {          nameCount(){              return  this.$store.getters.getNameLen          }     }

2.使用 mapGetters,引入mapGetters,使用个结构赋值的方法,将getters里面的方法映射到局部计算属性上,如果是数组则跟getters里面的方法名同名,对象可以修改名称,同mapState一样

人数:{

{ getNameLen }}

import {mapGetters} from 'vuex'  computed: {       ...mapGetters([         "getNameLen"       ]),       ...mapState({         nameArr: 'names',       })  }

Actions

Action类似于mutation,不同在于

  • action可以包含异步操作,而mutation只能是同步的

  • mutation是直接修改state里面的数据状态,而且action是commit一个mutation来记录修改状态。

让我们通过一个简单例子来实现一个简单的action:

1.修改 config index.js,引入url模块,修改dev配置里面的proxyTable,建一个与src同级的static目录,里面放一个

getName-time0.json文件,模拟本地http请求返回的json数据,重启服务, npm run dev 访问 http://localhost:8080/dataweb/getName?time=0
就能请求到static里面的json文件

url=require('url');   proxyTable: {         '/dataweb': {           target: 'http://localhost:8080',           changeOrigin: true,           pathRewrite: function(path, req) {             var urlParsed = url.parse(req.url, true),               query = urlParsed.query,               pathname = urlParsed.pathname.replace(/\/*$/g,'');             pathname = pathname.substring(pathname.lastIndexOf('/'));             Object.keys(query).forEach((key) => {               pathname += ('-' + key + query[key]);             });             pathname = '/static' + pathname + '.json';             console.log('proxy request ' + path + ' to ' + pathname);             return pathname;           }         }       }
{    "data":["赵钱","王五","孙刘"]  }
  1. 创建actions,修改store.js,引入vue-resource,actions是通过提交mutations来修改状态,所以在mutations增加一个getNames方法

    state里面增加一个data字段记录数据,actions增加一个getData方法。getDate有一个默认的context参数,这个参数具有跟store实例相同的属性和方法
    通过调用context.commit提交一个mutation,或者我们可以通过es6里面的结构赋值传入一个{commit},第二个参数 _param是我们分发action传入的参数

    import Vue from 'vue';import vuex from 'vuex';import VueResource from 'vue-resource';Vue.use(VueResource);Vue.use(vuex);export default new vuex.Store({  state:{ time:new Date().getTime(), data:[], names:["张三"]  },  mutations:{ pushName (state,thisName){   state.names.push(thisName.name) }, getNames(state,data){   state.data=data.list; }  },  getters:{ getNameLen:state=>{   return state.names.length }  },  actions:{  getData({ commit },_param){    return Vue.http.get('/dataweb/getName',{      params:_param.data    }).then((respons)=>{      commit({        type:'getNames',        list:respons.data      });    })  }  } })
  2. 修改app.vue组件,template里面增加一个按钮

     

    {

    { values }}   

data数据里面增加一个_data存储数据,methods里面增加一个searchName方法,派发getDate事件,并且传入data参数,actions的方法返回的promise,可以被store.dispatch 处理,并且store.dispatch 仍旧返回一个promise

getData里面的promise返回成功则更新this._data数据,失败则输出获取数据失败

data(){          return {            msg: 'Welcome to Your App.vue components',            addName: '',            nameData:[],          }    },                       methods: {      searchName(){         this.$store.dispatch({            type:'getData',            data:{ time:0 }         }).then(()=>{            this.nameData=this.$store.state.data         },()=>{            console.log('获取数据失败')         })                   }        }

从上面的例子我们了解到,点击一个按钮发生了这些操作;

  1. 定义一个getData的action 异步调用一个请求,请求成功,commit一个getNames的mutations,修改state的data数据

  2. 执行searchName事件,用$store.dispatch派发一个getData的actions,并且传入data:{time:0}的参数

  3. dispatch返回的promise成功,就表示getDate里面的commit已经执行完毕,state.data已经有数据,更新当前this._nameData,循环输出数据

在methods派发action除了实例的这种以对象形式派发,还有三种

  • 以载荷方式

    this.$store.dispatch('increment',{         data:{           time:1         }  })
  • 在methods里面使用 mapActions 方式 映射action

    import {mapActions} from 'vuex';  //数组形式  调用直接this.getDate  ...mapActions([        'getData'   ]),    //对象形式   this.searchName  等同于 this.getData  ...mapActions({      searchName:'getData'   })

    修改methods里面的searchName方法

    searchName(){        this.getDate({          data:{            time:0          }        }).then(()=>{          this.nameData=this.$store.state.data        },()=>{          console.log('数据失败')        })      }

vuex还有一个Modules概念,本篇文章就介绍这么多了,等学习完modules,在补充。。。。。

转载地址:http://hfagx.baihongyu.com/

你可能感兴趣的文章
程序员最喜爱的12个Android应用开发框架二(转)
查看>>
vim学习与理解
查看>>
DIRECTSHOW在VS2005中PVOID64问题和配置问题
查看>>
MapReduce的模式,算法以及用例
查看>>
《Advanced Linux Programming》读书笔记(1)
查看>>
zabbix agent item
查看>>
一步一步学习SignalR进行实时通信_7_非代理
查看>>
AOL重组为两大业务部门 全球裁员500人
查看>>
字符设备与块设备的区别
查看>>
为什么我弃用GNOME转向KDE(2)
查看>>
Redis学习记录初篇
查看>>
爬虫案例若干-爬取CSDN博文,糗事百科段子以及淘宝的图片
查看>>
Web实时通信技术
查看>>
第三章 计算机及服务器硬件组成结合企业运维场景 总结
查看>>
IntelliJ IDEA解决Tomcal启动报错
查看>>
默认虚拟主机设置
查看>>
php中的短标签 太坑人了
查看>>
[译] 可维护的 ETL:使管道更容易支持和扩展的技巧
查看>>
### 继承 ###
查看>>
数组扩展方法之求和
查看>>