Vuex核心介绍

Vuex简介

Vuex是一款状态管理的Vue插件。插件注册之后会向Vue的原型添加一个$store属性用来存储Vuex实例,组件内容可以通过该属性来访问Vuex中的state,或通过响应的方法修改state中的属性。

Vuex执行流程

官网中Vuex的执行流程很清晰的表达了Vuex的状态流转过程:
在这里插入图片描述

  • 通过差值表达式或指令将state绑定到视图Vue Component上。
  • 要想改变 state 中的状态需要通过触发事件来提交Mutations中改变state的方法的请求。
  • 异步任务需要在Actions中的方法中定义,然后在方法中通过提交Mutations中改变state的方法的请求来改变state。Actions不能直接改变state。

Vuex核心概念

  • state
    单一状态树,用来存储Vuex管理的状态。是一个响应式的对象,state中的数据改变,绑定的视图也会自动更新。
    定义:

    state: {
     count: 0,
      msg: 'Hello Vuex'
    },
    

    在视图中绑定state有两种方法:

    1. 通过$store.state来绑定
      <div id="app"> 
          <h1>count: {{$store.state.count}}</h1> 
          <h1>msg: {{$store.state.msg}}</h1>
       </div>
      
    2. 通过mapState方法将要绑定的state状态映射到computed计算属性中,然后像使用组件的计算属性一样使用它
      <template>
        <div id="app">
          <h1>State:</h1>
          count: {{count}}
          msg: {{msg}}
        </div>
      </template>
      <script>
      import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
      
      export default {
        computed: {
          ...mapState(['count', 'msg']),
          // ...mapState({num: 'count', message: 'msg'}), // key为映射后的计算属性,val是state中的状态属性
        }
      }
      </script>
      
      mapState接收一个数组或对象,返回一个对象,数组的每一项对应返回对象的属性。
  • Getters
    类似计算属性,适用于要将state中的数据进行简单处理,然后返回。
    定义:

    getters: {
      reverseMsg(state) {
        return state.msg.split('').reverse().join('')
      }
    },
    

    在组件内使用Getter也有两种方法:

    1. 通过$store.getters绑定
      <p>ReverseMsg: {{$store.getters.reverseMsg}}</p>
      
    2. 通过mapGetters方法映射到computed计算属性中,然后像使用组件的计算属性一样使用它。mapGetters的使用和mapState类似
      <template>
        <div id="app">
          <h1>Getters:</h1>
          <p>ReverseMsg: {{$store.getters.reverseMsg}}</p>
          <!-- <p>ReverseMsg: {{rvm}}</p> -->
        </div>
      </template>
      <script>
      import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
      
      export default {
        computed: {
           ...mapGetters(['reverseMsg'])
          // ...mapGetters({ rvm: 'reverseMsg'}),
        }
      }
      </script>
      
  • Mutations
    更改state中状态的唯一方法是提交mutation,mutation必须是同步执行的。
    定义:

    mutations: {
      increment(state, payload) {
        state.count += payload
      }
    },
    

    mutation的提交也有两种方法:

    1. 通过$store.commit(‘type’, payload)提交
      <button @click="$store.commit('increment', 1)">mutation</button>
      
    2. 通过mapMutaions()方法将mutation映射到methods中。
      <template>
        <div id="app">
          <h1>Mutation:</h1>
          <button @click="$store.commit('increment', 1)">mutation</button>
          <!-- <button @click="increment(1)">mutation</button> -->
        </div>
      </template>
      <script>
      import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
      
      export default {
      
        methods: {
          ...mapMutations(['increment']),
          // increment(val) { // 上面等价于
          //   this.$store.commit('increment', val)
          // }
        }
      }
      </script>
      
      通过mapMutations方法生成的方法等价于上面注释的方法。
  • Actions
    执行异步修改state的方法,但具体的执行过程还需要commit mutation来完成。
    定义:

    actions: {
      asyncIncrement(content, payload) {
        setTimeout(() => {
          content.commit('increment', payload)
        }, 3000)
      }
    },
    

    actions的使用的两种方法:

    1. 通过$store.dispatch派发
      <button @click="$store.dispatch('asyncIncrement', 5)">action</button>
      
    2. 通过mapActions将action映射到methods中
      <template>
        <div id="app">
          <h1>Actions:</h1>
          <button @click="$store.dispatch('asyncIncrement', 5)">action</button>
          <!-- <button @click="asyncIncrement(5)">action</button> -->
        </div>
      </template>
      <script>
      import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
      
      export default {
        methods: {
           ...mapActions(['asyncIncrement'])
        }
      }
      </script>
      
  • Modules
    将单一状态树拆分成多个模块,可以定义自己的state,mutations,actions,getters以及嵌套的modules。

    子模块中的state会合并store的state中:访问时通过$store.state.[moduleName].[state]来访问子模块中的state。

    子模块中的mutations、actions,getters会合并到state中的mutations、actions,getters中。mutations、actions中的属性将会变成数组,保存所有的同名的属性,当commit时,对应数组内容方法都会执行。getters则还是对象,根模块中的getters和子模块的getters不能有重名。
    在这里插入图片描述
    定义:

    	const products = {
    	  namespaced: true,
    	  state: {
    	    list: [
    	      {
    	        id: 1,
    	        name: 'Product A'
    	      },
    	      {
    	        id: 2,
    	        name: 'Product B'
    	      }
    	    ],
    	    nums: 0,
    	  },
    	  mutations: {
    	    reset(state) {
    	      state.list = []
    	    },
    	    increment(state, payload) {
    	      state.nums += payload;
    	    }
    	  },
    	  actions: {},
    	  getters: {
    	    sumWithRoot(state, getters, rootState) {
    	      return state.nums * rootState.count;
    	    }
    	  }
    	}
    	
    	export default new Vuex.Store({
    	  modules: {
    	    products,
    	  }
    	})
    

    使用:和根模块的使用类似,通过$store或通过mapXXX方法映射到组件内容的状态和方法。

    <template>
      <div id="app">
        <h1>Modules:</h1>
        <!-- <p>Product Nums: {{$store.state.products.nums}}</p>
        <p>Product Nums Width Root: {{sumWithRoot}}</p>
        <p>{{$store.state.products.list}}</p>
        <button @click="$store.commit('reset')">reset</button> -->
        <p>Product Nums: {{$store.state.products.nums}}</p>
        <button @click="$store.commit('products/increment', 3)">product nums increment</button>
        <!-- <p>Product Nums Width Root: {{sumWithRoot}}</p> -->
        <p>{{$store.state.products.list}}</p>
        <button @click="$store.commit('products/reset')">reset</button>
      </div>
    </template>
    <script>
    import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
    
    export default {
      computed: {
         ...mapGetters('products', ['sumWithRoot'])
      },
    }
    </script>
    

    子模块默认不开启命名空间,如果想要开启命名空间需要在子模块定义添加namespaced属性并设置为true即可。

    开启命名空间之后,store中的getters,mutations,actions中的属性都将拼接上子模块名。map 函数的第一个参数可以传入命名空间的名字。
    在这里插入图片描述

Vuex插件

Vuex 插件就是一个函数,它接收 store 作为唯一参数,函数中可以注册函数,在让它在所有mutation之后执行。

插件应该在new Vue.Store之前定义。

在插件中不允许直接修改状态——类似于组件,只能通过提交 mutation 来触发变化。

// vuex 插件
const saveLocalStorage = store => {
  store.subscribe((mutations, state) => {
    if (mutations.type.startsWith('carts/')) {
      window.localStorage.setItem(
        'carts',
        JSON.stringify(state.carts.cartProducts)
      )
    }
  })
}

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules: {
    products,
    carts
  },
  plugins: [saveLocalStorage]
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值