關於Vuex的詳解
首先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