Vuex的理解与运用

来源:互联网 发布:apache cassandra 编辑:程序博客网 时间:2024/06/18 17:24

初步认识Vuex

Vuex是什么?

  • 官方解释
    Vuex是一个专为Vue开发的应用程序的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
  • 我的理解
    Vuex采用类似全局对象的形式来管理所有组件的公用数据,如果你想想修改这个全局对象的数据,是可以的,但没那么简单,你得按照Vuex提供的方式来修改,不能自己随意用自己的方式来修改。

Vuex的好处

  • 状态存储是响应式:当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 不能随意修改Vuex的状态:改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。

Vuex的适用场景

不是所有使用vue开发的SPA(single page application)单页应用都适合采用Vuex。如果你的应用是个小型的应用,组件不多,组件之间的状态依赖不多,关系清晰容易维护,也就是说不同组件之间很少有数据之间的关联的话,那么你大可不用Vuex来开发。反之,如果你开发的是较大型的应用,出现多个视图组件共同依赖一个状态,这个状态相当于我们的全局对象数据,其他组件的改动,会影响到它,反之,它的修改也需要更新其他关联的组件,那么Vuex就很适用。比如:商城系统,外卖系统等等。

理解Vuex的核心概念

Store

要使用Vuex,我们要创建一个实例 store ,我们称之为仓库,利用这个仓库 store 来对我们的状态进行管理。

//创建一个 store const store = new Vuex.Store({});

State

Vuex 使用单一状态树,用一个对象State包含了整个应用层级的所有状态,你可以理解为这些状态就是一堆全局变量和数据。

//创建一个 store const store = new Vuex.Store({    //state存储应用层的状态    state:{        count:5  //总数:5    } });

上面的例子中,假设我们有一个全局状态count的值为5。那么,我们就可以将其定义为 state 对象中的key和value,作为全局状态供我们使用。

Getter

还记得Vue中的计算属性computed 吗?当我们需要在data的基础上再派生一些状态的时候,就会使用computed 来实现。同样,当我们需要从 state 中派生出一些状态的时候,就会使用到getters,你可以将 getters 理解state的计算属性。

getters 接受 state 作为其第一个参数:

const store = new Vuex.Store({   //state存储应用层的状态   state:{      count:5  //总数:5    },    //派生出来的状态   getters:{      //ES6 的箭头函数语法    newCount:state => state.count * 3    } });

假设我们要在state.count的基础上派生出一个新的状态newCount出来,就适合使用我们的getters

Mutation

Vuex相比传统的全局变量有两个优势,其中一个是Vuex中的状态不能随意修改,要修改必要按照Vuex提供的方式才能修改。

Vuex给我们提供修改仓库 store 中的状态的唯一办法就是通过提交 mutation。我们来看看如何定义一个mutation:

const store = new Vuex.Store({    //state存储应用层的状态    state:{        count:5  //总数:5    },    //更改store状态的唯一途径    mutations:{        increment(state){            state.count ++;        }    } });

我们再 mutations 中定义了一个叫increment的函数,函数体就是我们要进行更改的地方,可以看到,我们只是简单地对 state 中的count进行了自增运算。

使用mutations:
非常简单,Vuex要求我们要想通过 mutations 更改内容,就必须提交 mutation,语法如下

//提交一个名为increment的mutationstore.commit('increment');

我们再提交commit时候,字符串参数increment,就是对应在mutations中的increment。

此外,store.commit( ) 还接受其他额外的参数,比如:

 //... //更改store状态的唯一途径 mutations:{    increment(state,n){        state.count += n;    } } //... store.commit('increment',10);

Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作,通过 store.dispatch 方法触发
actions: {    increment (context) {      context.commit('increment')    }  }//...store.dispatch('increment')

mutation都是同步事务,而异步操作需要在action中处理,看官方文档对于action的讲解非常易懂,这里对action不做具体介绍。

使用Vuex实现一个简单的计算器

要实现的效果如图:
这里写图片描述

  • 自定义keyboard组件
<template>  <div class="val-cont" @click="getKeyboardValue" :data-value="val">    {{val}}  </div></template><script type="text/ecmascript-6">  export default {    props: {      val: ''    },    methods: {      getKeyboardValue (event) {        let value = event.target.dataset.value        this.$store.commit('calculate', value)      }    }  }</script><style lang="scss" scoped>  //...</style>
  • 创建store
 const store = new Vuex.Store({    state:{       result:"",//运算结果       enter:""  //输入的值    } });
  • 定义名为calculate的mutations
const mutations = {  calculate: (state, value) => {    if (value === '=') {      state.result = evil(state.enter)      state.enter += value    } else if (value === 'clear') {      state.result = state.enter = ''    } else {      state.enter += value    }    // 代替eval,eslint禁用eval    function evil (fn) {      var Fn = Function      return new Fn('return ' + fn)()    }  }}
  • 页面布局以及使用修改mutations
<template>  <div class="calu clear">    <div class="result">      <!--计算结果:-->      {{result}}    </div>    <div class="enter">      <!--输入式子-->      {{enter == "" ? 0 : enter}}    </div>    <div class="list">      <keyboard v-for="item in keys" :val="item"></keyboard>    </div>  </div></template><script>  import Keyboard from '../../components/keyboard.vue'  export default{    components: {      Keyboard    },    data () {      return {        keys: ['clear', '+', '-', '*', '/', '0', '1', '2', '3',          '4', '5', '6', '7', '8', '9', '='        ]      }    },    computed: {      result () {        //通过this.$store获取仓库的数据result        return this.$store.state.result      },      enter () {        //通过this.$store获取仓库的数据enter        return this.$store.state.enter      }    }  }</script><style lang="scss" scoped>  //...</style>
  • 运行效果
    这里写图片描述

Vue爬坑之路还很漫长

原创粉丝点击