首先Vuex是状态管理工具,Vuex是应用于Vue中,说一下Vuex吧
开始Vuex之前,我们先了解一下一张图
从图中能看到几个关键的组成部分,Vue Component,Actions,Mutations,State,是的,其实整个Vuex的状态管理就是呈现这么一个类似闭环的结构,
但是有一点需要注意的是,我们想要进行一个操作是,是不能省去某个操作的(Action除外)
现在大致解释一下这个图,首先我们需要定义一个全局状态State,当我们的组件进行某些操作时需要改变这个全局状态,那就通过dispatch触发我们的Action,然后再由Action通过Commit请求到Mutations才能改变我们定义的State,这里需要注意的是,State是不能直接改变的,必须通过Mutation的操作才能改变,与此同时,这是一个异步的操作。那么同步的时候是怎么操作的呢?其实很简单,同步的时候我们就不可以不用dispatch了,就可以直接commit给Mutations进行状态的修改了。这里放一个做的购物车小demo
开始的第一步肯定是引入vuex
yarn add vuex
然后是定义我们的store
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) import products from './modules/products' import cart from './modules/cart' export default new Vuex.Store({ modules: { products, cart } })
为了充分的体现我们vue的组件化思想,这里我将cart和products进行了拆分
这里是cart的部分代码
const getters = { beautifulItems (state, getters, rootState) { return state.items.map((item, index) => { let { title, price } = rootState.products.all.find( product => product.id === item.id) return { title, price, quantity: item.quantity } }) }, totalPrice (state, getters) { return getters.beautifulItems.reduce((total, product) => { return total + product.price * product.quantity }, 0) } } const mutations = { push (state, item) { state.items.push(item) }, update (state, item) { item.quantity++ } } const actions = { addToCart ({ commit, state }, product) { if (product.inventory > 0) { let item = state.items.find( item => item.id === product.id ) if (!!item) { commit('update', item) } else { commit('push', { id: product.id, quantity: 1 }) } commit('products/update', { id: product.id }, { root: true }) } } }
这里是products
const actions = { async getAllproducts ({ commit }) { let products = await shop() commit('setProducts', products) } } const mutations = { setProducts (state, products) { state.all = products }, update (state, { id }) { let product = state.all.find( product => product.id === id) product.inventory-- } }
到这一步的时候别忘了在main.js中引入一下Store,不然组件内是获取不到的
接下来就到组件内的引用了,下面是Products组件的代码,
<template> <ul> <li v-for="product of products" :key="product.id"> {{ product.title }} - {{ product.price }} <br /> <button :disabled="product.inventory === 0" @click="addToCart(product)">放入购物车</button> </li> </ul> </template> <script> import { mapState, mapMutations, mapActions } from 'vuex' export default { computed: { ...mapState('products', { products: 'all' }) }, methods: { addToCart (product) { this.$store.dispatch('cart/addToCart', product) } }, created () { this.$store.dispatch('products/getAllproducts') } } </script>
其实在这里对状态的获取方式有很多种,不一定是上面我写的这种,
还有就是其实图里面是没有getter的
其实getter就是运行中带缓存的,算是对提升性能方面做了些优化工作,言外之意也是鼓励大家多使用getter。
这里附上我的demo地址:
https://github.com/yangshu17/vuex-demo-cart