pinia之前的vuex前段时间介绍了一下组件通信的部分父子组件之间的通信,今天就来给大家分享一个任何组件之间的通信方法
前段时间介绍了一下组件通信的部分父子组件之间的通信,今天就来给大家分享一个任何组件之间的通信方法,这个方法就是vuex。它就不再仅仅局限于父子组件的通信了,而是全局的状态共享,任何组件都能够使用到它里面的数据。
什么是vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式与库。这么说可能有点晕,简单的理解就是实现组件间数据共享的一种方式,就类似于一个数据仓库,组件需要数据直接去取就行了。
vuex的核心概念
1. state
state代表了应用程序的状态或数据,这些数据会被多个组件所共享,就相当于一个数据存储容器,但是我们只能访问这里面的数据,并不能直接修改state里面的内容,而是要通过Mutations来修改数据内容,这也是唯一一个修改数据状态的方法。我们在state里面可以定义简单的一些数据,如果数据较多的话,我们可以使用model来模块状态。简单的数据状态具体表示如下:
state:{
count:0
},
2. mutations
这是更改状态的唯一途径,同时也保证了状态更改的可追踪性和可预测性。但是它必须是一个同步函数,也就是说它不能进行复杂的计算,如从中向后端获取数据等异步的操作,他必须是一个有明确且清晰的状态修改规定。所以我们通常用actions来进行复杂的操作,然后通过commit提交一个mutation。当然我们也可以在任何一个地方通过this.store.commit来提交。如:
const mutations = {
setProducts(state,products){
state.all = products
}
}
这里面的setProducts
就是我们通过commit提交的mutation名称。
3. actions
actions类似于mutations,但是他提交的是mutations,而不能直接来修改数据状态,还是要通过mutations来修改状态。另外他可以进行任意的异步操作。如果我们需要进行修改状态,就可以在actions里面定义一个方法来实现这个修改状态。如:
const actions = {
// api 请求 -> 提交mutations
// commit vuex给actions可以commit mutations的API
getAllProducts({commit}){
API.getProducts((products)=>{
console.log(products);
commit('setProducts',products) // 提交mutations 以及她的值
})
}
}
actions需要使用store.dispacth方法来进行触发,如
store.dispatch('products/getAllProducts')
这就表示我们在别的地方触发products这个store模块里的actions的getAllProducts这个方法。
4. getters
这类似于 Vue 的计算属性,Getters 接收 state 作为其第一个参数并返回处理后的数据,主要用于当需要让多个组件访问同一份状态时,避免在每个组件中重复定义计算属性。例如我们在完成一个购物车功能时,需要一个数据来记录购物车的总金额,如果我们重新定义一个状态的话就会出现数据杂糅的现象。我们可以在getters里面定义一个计算方法来计算总金额。如下:
cartTotalPrice:(state,getters) => {
return getters.cartProducts.reduce((total,product)=>{
return total + product.price * product.quantity
},0)
}
5. model
这用来实现模块化状态,防止我们的应用太大时,store对象非常臃肿。这样我们就可以将其分割成一个个的小模块。
modules:{
cart, // 购物车状态
products //商品状态
}
怎么引入vuex
- 首先我们需要先下载vuex,通过npm install vuex
- 在全局注册这个组件,也就是
app.use(store)
- 然后通过createStore返回一个单一状态树
export default createStore()
,状态就是树上的结点。
怎么使用vuex
我这里通过一个购物车功能来演示一下vuex的用法。
<template>
<ul>
<li
v-for="product in products"
:key="product.id"
>
{{ product.title }}-{{ product.price }}
<br>
<button
:disabled="!product.inventory "
@click="addProductToCart(product)">
Add to Cart
</button>
</li>
</ul>
</template>
<script setup>
import { computed,onMounted } from 'vue';
import {useStore} from 'vuex'
const store = useStore();
const products = computed(()=>store.state.products.all)
onMounted(()=>{
store.dispatch('products/getAllProducts')
})
const addProductToCart = (product)=>{
// 修改状态 dispatch action -> commit mutation
store.dispatch('cart/addProductToCart',product)
}
</script>
<style lang="scss" scoped>
</style>
这里我主要演示了dispatch来触发actions。
import { createStore } from 'vuex'
import cart from './modules/cart'
import products from './modules/products'
// 仓库 ,分个子仓
export default createStore({
//全局状态 数据多就不好维护
state:{
},
// 模块化状态
modules:{
cart, // 购物车状态
products //商品状态
}
})
这里主要就是模块化store,为了防止store变得过于臃肿。
const state = {
items:[]
}
const getters = {
cartProducts:(state,getters,rootState)=>{
return state.items.map(({id,quantity})=>{
const product = rootState.products.all.find(product => product.id===id)
return {
id: product.id,
title: product.title,
price: product.price,
quantity: quantity
}
})
},
cartTotalPrice:(state,getters) => {
return getters.cartProducts.reduce((total,product)=>{
return total + product.price * product.quantity
},0)
}
}
const actions = {
addProductToCart({commit,state}, product){
if(product.inventory > 0){
const cartItem = state.items.find(item => item.id===product.id)
if(!cartItem) {
// 如果购物车中没有该商品,则添加该商品
commit('pushProductToCart',{id:product.id})
}else{
// 如果购物车中有该商品,则直接加一
commit('incrementQuantity', cartItem)
}
commit('products/decrementProductInventory',{id:product.id},{root:product})
}
}
}
// 跟 state 的操作在这里 这就是比pinia复杂的地方
// 规定了数据可以怎么变化
// mutations 就是财务 对数据的修改原则
const mutations = {
pushProductToCart(state,{ id }){
state.items.push({
id,
quantity:1
})
},
incrementQuantity(state,cartItem){
cartItem.quantity++
}
}
// store.product.all
export default {
namespaced:true,
state,
getters,
actions,
mutations
}
这是cart模块的store,这里的getters用来进行数据的计算,actions对数据进行操作,之后提交为mutation,交给mutations修改它的状态。
总结
为了减少文章篇幅,我仅仅是拿出了几个文件来介绍vuex的使用,大家可以自行看我提供的部分代码,相信大佬们可以很快就能弄清楚具体的用法。vuex它适合大型的项目,用来进行数据管理,这样的数据管理更严格,因为他就只有mutations能够修改状态,通过commit提交修改。但是这样工序也是比较复杂的,所以现在又有一个新的方法来实现数据管理功能了,那就是pinia。pinia在vue3 推出 hooks,更方便,而且它自带模块化,没有mutations,数据管理更加的自由。
转载自:https://juejin.cn/post/7402079591717978146