Vue使用 Vuex 作为状态管理

【Vue】使用 Vuex 作为状态管理

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库。它使用单一状态树,这意味着这个对象包含了全部的应用层级状态,并且以一种相对集中的方式存在。这也意味着,通常单个项目中只有一个 Vuex store。Vuex 的核心概念和功能包括:

  1. 状态(State):Vuex 使用单一状态树,即一个对象包含了整个应用的状态。状态存储是响应式的,当 Vue 组件从 store 中读取状态时,若状态发生变化,相关组件也会相应更新。

  2. 视图(View):Vue 组件输出状态的可视化表示。

  3. 行为(Actions):响应在 view 上的用户输入导致的状态变化。

除此之外,Vuex 还有以下几个核心概念:

  1. Getters:允许组件从 store 中获取状态,同时可以对状态进行一些预处理。

  2. Mutations:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler)。

  3. Actions:类似于 mutations,不同在于它们提交的是 mutations,而不是直接变更状态。Actions 可以包含任意异步操作。

  4. Modules:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决这个问题,Vuex 允许我们将 store 分割成模块(module)。

Vuex 是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会自动更新。这也意味着 Vuex 中的状态不能直接改变,只能通过显式提交 mutations 来更改。

使用案例

假设我们正在开发一个购物车应用,用户可以将商品添加到购物车中,查看购物车中的商品,以及清空购物车。在这个例子中,我们将创建一个 Vuex store 来管理购物车的状态。

首先,你需要在你的 Vue 项目中安装和引入 Vuex:

pnpm install vuex --save

然后,在你的 Vue 项目中创建一个 Vuex store:

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    cart: []
  },
  getters: {
    cartItemCount: state => {
      return state.cart.length
    },
    cartTotalPrice: state => {
      return state.cart.reduce((total, item) => {
        return total + item.price * item.quantity
      }, 0)
    }
  },
  mutations: {
    addToCart(state, item) {
      const found = state.cart.find(product => product.id === item.id)

      if (found) {
        found.quantity++
      } else {
        state.cart.push({ ...item, quantity: 1 })
      }
    },
    removeFromCart(state, item) {
      const index = state.cart.indexOf(item)
      if (index > -1) {
        state.cart.splice(index, 1)
      }
    },
    clearCart(state) {
      state.cart = []
    }
  },
  actions: {
    addToCart({ commit }, item) {
      commit('addToCart', item)
    },
    removeFromCart({ commit }, item) {
      commit('removeFromCart', item)
    },
    clearCart({ commit }) {
      commit('clearCart')
    }
  }
})

在上面的代码中,我们定义了:

  1. State:购物车数组 cart。
  2. Getters:cartItemCount 和 cartTotalPrice 用于获取购物车中的商品数量和总价。
  3. Mutations:addToCart、removeFromCart 和 clearCart 用于修改购物车的状态。
  4. Actions:包装了 mutations 的方法,这里是 addToCart、removeFromCart 和 clearCart。

最后,在你的 Vue 组件中使用这个 store:

// 在一个组件中
<script>
import { mapGetters, mapActions } from 'vuex'

export default {
  computed: {
    ...mapGetters(['cartItemCount', 'cartTotalPrice'])
  },
  methods: {
    ...mapActions(['addToCart', 'removeFromCart', 'clearCart']),
    addItemToCart(item) {
      this.addToCart(item)
    },
    removeItemFromCart(item) {
      this.removeFromCart(item)
    },
    emptyCart() {
      this.clearCart()
    }
  }
}
</script>

完整代码

<template>
  <div class="shopping-cart">
    <h2>购物车</h2>

    <div v-if="cartItemCount === 0">
      购物车为空。
    </div>

    <div v-else>
      <ul>
        <li v-for="(item, index) in cart" :key="index">
          {{ item.name }} - {{ item.quantity }} x {{ item.price }}元
          <button @click="removeItemFromCart(item)">移除</button>
        </li>
      </ul>

      <p>总价: {{ cartTotalPrice }}元</p>

      <button @click="emptyCart">清空购物车</button>
    </div>
  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'

export default {
  name: 'ShoppingCart',

  computed: {
    ...mapGetters(['cartItemCount', 'cartTotalPrice']),
    cart() {
      return this.$store.state.cart
    }
  },

  methods: {
    ...mapActions(['removeFromCart', 'clearCart']),

    removeItemFromCart(item) {
      this.removeFromCart(item)
    },

    emptyCart() {
      this.clearCart()
    }
  }
}
</script>

<style scoped>
.shopping-cart {
  border: 1px solid #ddd;
  padding: 20px;
  border-radius: 5px;
  margin: 20px auto;
  width: 300px;
}

.shopping-cart h2 {
  color: #333;
}

.shopping-cart ul {
  list-style-type: none;
  padding: 0;
}

.shopping-cart ul li {
  margin-bottom: 10px;
  line-height: 1.6;
}

.shopping-cart button {
  background-color: #42b983;
  color: white;
  border: none;
  padding: 5px 10px;
  margin-left: 10px;
  border-radius: 3px;
  cursor: pointer;
}

.shopping-cart button:hover {
  background-color: #333;
}
</style>

在这里插入图片描述