上篇文章介绍了父子组件之间的通信,但是当碰到爷孙组件或者兄弟组件时,使用父子组件之间的Props等方法就要一层一层传递,非常麻烦且不优雅,但是有个非常简洁的方法可以解决,那就是今天要介绍的菠萝了。
今天就让我们通过一个小demo来认识一下pinia在仓库中的概念,Pinia 就是一个用于 Vue.js 应用程序的轻量级状态管理库,可用于跨组件,页面进行状态共享。
比如;写一个简单的购物车,实现以下效果。
当然,实现上面效果只需要用一个组件或一个页面就可以完成,但是我们可以通过这个简单的例子来了解 pinia 的用法,实现跨组件状态共享,就把上面的商品列表写在List.vue组件上,下面的商品数量统计和合计写在Car.vue组件上,如下。
需要实现点击每个加入购物车,购物车中的商品数量以及合计会跟着发生变化,我们就需要用到仓库的概念,创建一个仓库,将共用的数据放到仓库里面,取数据时再到仓库中去取。
创建仓库就可以使用到 pinia 状态管理库,那么这个 pinia 怎么用呢?
基本步骤
- 安装pinia
npm install pinia
2. 创建 pinia 实例,在项目的 store 文件夹中创建一个 index.js 文件,并初始化 pinia 实例。这个只是为了让pinia的源代码跟vue的源代码可以融合使用。
import { createPinia } from 'pinia'
const store = createPinia()
export default store
3. 然后在main.js全局里面use它全局生效,这样项目里每个地方都可以使用这个仓库了。
import store from './store/index.js'
createApp(App).use(store)
4. 在store下面创建一个car.js,在里面开创一个可用的仓库,将商品列表的数据数组放入这个仓库,defineStore执行结果是一个函数体。
import { defineStore } from 'pinia' // 开创一个可用的仓库
export const useCarStore = defineStore('car', () => {
state:()=>{
return {
listArr:[xxx]
}
}
}
export default useCarStore // 抛出这个仓库
- 然后就是如何将它取出来用了。在List.vue中引入这个仓库。
import useCarStore from '../store/car.js'
const carStore = useCarStore() // useCarStore是一个函数
打印出这个carStore如下;
这样就可以把仓库中的数据取出来了。直接使用carStore.listarr就是这个数组了,然后直接将它循环就可以渲染到页面上了。
pinia 的使用
上面的是老版本vuex的写法,pinia的前身就是vuex。
在pinia中:
ref()就是state属性computed()就是gettersfunction()就是actions
显然新的语法更符合vue的语法。所以我们使用新的语法,同样defineStore先接收一个唯一的id,然后接收一个回调函数,里面可以直接定义数组,然后再return出这个数组,然后List.vue中就可以直接carStore.listArr获取这个数组。
export const useCarStore = defineStore('car', ()=>{
const listArr=[]
return {
listArr
}
})
然后回到我们的购物车,直接将定义在仓库中的listArr通过v-for遍历渲染到页面上,然后给加入购物车这个按钮绑定点击事件,并且传入该物品的信息(item)。
<template>
<div>
<ul>
<li v-for="(item, i) in carStore.listArr" :key="index">
<img :src="item.pic" alt="">
<p> {{ item.name }}</p>
<p>{{ item.desc }}</p>
<div class="price">
<span>{{ item.price }}</span>
<button @click="addCar(item)">加入购物车</button>
</div>
</li>
</ul>
</div>
</template>
<script setup>
import { useCarStore } from '../store/car.js'
const carStore = useCarStore()
console.log(carStore.listArr);
const addCar = (item) => {
carStore.addSelectArr(item) // 调用仓库中的方法
}
</script>
然后在仓库中定义addSelectArr函数。
// 需要注意要将其设置成响应式
const selectArr = reactive([]) // 选中的商品,用来后面计算商品数量和总价
const addSelectArr = (item) => {
selectArr.push(item)
}
然后就是在仓库中定义两个变量用来计算商品数量和商品总价。
const selectNum = computed(() => {
return selectArr.length
})
const totalPrice = computed(() => {
let totalPrice = 0; // 总价
for (let i = 0; i < selectArr.length; i++) {
totalPrice += selectArr[i].price
}
return totalPrice;
})
最后在Car.vue中渲染selectNum和totalPrice
仓库中的代码如下;
这样就使用pinia完成这个小demo了。
注意:
- 俩个组件之间想要实现数据共用,就将数据定义在仓库当中,然后俩个组件各自引入同一个仓库对象
- 仓库中的数据修改,应该使用仓库中的方法进行修改,而不要将数据引入到组件中后修改
好了,通过这个简单的购物车示例,我们了解了 Pinia 的基本用法,还体会到了它在 Vue.js 应用中实现跨组件状态共享的便捷性,当有爷孙等多层组件或兄弟组件之间的通信就可以使用这个菠萝了,最后。