vue3 使用的 Pinia

news/2024/11/25 5:42:27/

文章目录

  • 一、Pinia API与Vuex s4 有很大不同
  • 二、使用步骤
    • 1.安装
    • 2.使用
    • 3、组件中应用
    • 案例

在这里插入图片描述

官网:https://pinia.web3doc.top/


一、Pinia API与Vuex s4 有很大不同

  • 没有 mutations。mutations 被认为是非常几长的。最初带来了 devtools 集成,但这不再是问题
  • 不再有模块的嵌套结构您仍然可以通过在另一个 store 中导入和使用 store 来隐式嵌套 store,但 Pinia 通过设计提供扁平结构,同时仍然支持 store 之间的交叉组合方式。您甚至可以拥有 store 的循环依赖关系。
  • 更好 typescript 支持。无需创建自定义的复杂包装器来支持 TpeScript,所有内容都是类型化的,并且 AP 的设计方式尽可能地利用 TS 类型推断。
  • 不再需要注入、导入函数、调用它们,享受自动补全!
  • 无需动态添加 stores,默认情况下它们都是动态的,您甚至不会注意到。请注意,您仍然可以随时手动使用 store 来注册它,但因为它是自动的,所以您无需担心。
  • 没有命名空间模块。鉴于 store 的扁平架构,"命名空间"stre 是其定义方式所固有的,您可以说所有 stores 都是命名空间的.

Pinia 就是更好的 Vuex,建议在你的项目中可以直接使用它了,尤其是使用了TypeScript 的项目。

二、使用步骤

1.安装

yarn add pinia
// 或者使用 npm
npm install pinia 

2.使用

在main.ts里面映入

import { createApp ] from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
// 创建
const pinia = createpinia()
const app = createApp(App)
// 挂载到 Vue 根实例
app.use(pinia)
app.mount('#app')

新建store文件夹。在文件夹下面新建index.ts。

import { defineStore } from 'pinia'
// 1.定义并导出容器
// 参数1: 容器的 ID,必须唯一,将来 Pinia 会把所以的容器挂载到根容器
// 参数2: 选项对象
export const useMainStore = defineStore( 'main',{// 类似于组件的 data,用来存储全局状态的// 1、state必须是函数: 这样是为了在服务端染的时避免交叉请求导致的数据状态污染// 2、必须是箭头函数,这是为了更好的 TS 类型推导state: (){return {};},// 类似于组件的 computed,用来封装计算属性,有缓存的功能getters: {count10 (state) {  // state可选参数console.log('count10 调用了')return state.count + 10}},// 类似于组件的 methods,封装业务逻辑,修改 stateactions: {changestate (num:number) {this.count+=num}}
})
// 2.使用容器中的 state
// 3.修改 state
// 4.容器中的 action 的使用	

3、组件中应用

<template><div> {{mainStore.count }} </div><div> {{count }} </div><button @click="handleChangeState">修改数据</button><div>{{ mainStore.count10 }}</div><div>{{ mainStore.count10 }}</div>
</template>
<script lang="ts" setup>import {useMainStore } from ' .. /store'import { storeToRefs } from 'pinia'const mainStore = useMainStore( )console.log(mainStore.count )const { count] = storeToRefs(mainStore)//修改数据const handleChangestate = ()=>  {//  方式一: 最简单的方式就是这样mainStore.count++;// 方式二: 如果需要修改多个数据,建议使用 $patch 批量更新mainStore.$patch({count: mainStore.count + 1,})// 方式三:使用$patch 传递一个函数,也是批量更新mainStore.$patch( state=>{state.count++})// 方式四: 逻辑比较多的时候可以封装到 actions 做处理mainStore.changeState(10)}
</script>

如果在组件中把mainStore数据解构出来,那么数据不是响应式的了,需要使用storeToRefs 去解构。实质是将解构出来的数据做ref代理处理。

多个数据批量修改有利于性能优化,因为一个一个改数据会触发一次又一次的视图更新,批量修改只会触发一个视图更新。

注意:不能使用箭头函数定义 action,因为箭头函数绑定外部 this


案例

商品列表
。展示商品列表、添加到购物车
购物车
。展示购物车商品列表、展示总价格、订单结算、展示结算状态。

效果如下图:
在这里插入图片描述

新建商品组件 ProductList.vue

<template><ul><li v-for="item in productsStore.all">{{ item.title }} - {{ item.price }}---<button :disabled="item.inventory <= 0" @click="cartStore.addProductToCart(item)">添加到点物车</button></li></ul>
</template><script setup lang="ts">
import { useCartStore } from '../store/cart';
import { useProductsStore } from '../store/products';
const productsStore = useProductsStore()
const cartStore = useCartStore()// 加载数据
productsStore.loadAllProducts()
</script>

新建购物车 Shoppingcart.vue

<template><div class="cart"><h2>你的购物车</h2><p><i>请添加一些商品到购物车.</i></p><ul><li v-for="item in cartStore.cartProducts">{{ item.title }} - {{ item.price }} x {{ item.quantity }}</li></ul><p>商品总价: {{ cartStore.totalPrice }}</p><p><button @click="cartStore.checkout()">结算</button></p><p v-show="cartStore.checkStatus">结算 {{ cartStore.checkStatus }}</p></div>
</template>
<script setup Tang="ts">
import { useCartStore } from '../store/cart';
const cartStore = useCartStore()
</script>

在api文件下 新建 shops.ts 文件,用于模拟调用数据接口

export interface IProduct {id: numbertitle: stringprice: numberinventory: number // 库存
}
const _products: IProduct[] = [{ id: 1, title: 'iPad 4 Mini', price: 500.01, inventory: 2 },{ id: 2, title: 'HEM T-Shirt white', price: 10.99, inventory: 10 },{ id: 3, title: 'Charli XCX - Sucker cD', price: 19.99, inventory: 5 },
]export const getproducts = async () => {await wait(100)return _products}export const buyProducts = async () => {await wait(100)return Math.random() > 0.5
}
async function wait(delay: number) {return new Promise((resolve) => setTimeout(resolve, delay))
}

在src目录下新建store 文件,下面新建cart.ts和 products.ts
products.ts 代码如下:

import { defineStore } from 'pinia'
import {getproducts,IProduct} from "../test/api/shops"
export const useProductsStore = defineStore('products', {state: () => {return {all:[] as IProduct[] // 所以商品列表}},getters: {},actions: {async loadAllProducts () {const ret = await getproducts()this.all = ret},// 减库存decrementProduct(product:IProduct){const ret = this.all.find(item=> item.id === product.id) if(ret){ret.inventory--}}}
})

cart.ts 代码如下:

import { defineStore } from "pinia";
import { IProduct, buyProducts } from "../test/api/shops";
import { useProductsStore } from "./products"
type CartProduct = {quantity: number
} & Omit<IProduct, "inventory"> // 合并IProduct类型数据,Omit 合并IProduct的时候,去除inventory库存这个属性
// IProductexport const useCartStore = defineStore("cart", {state: () => {return {cartProducts: [] as CartProduct[],   // 购物车商品列表checkStatus: null as null | string,}},getters: {totalPrice(state) { // 计算总价return state.cartProducts.reduce((total, item) => {return total + item.price * item.quantity}, 0) // 初始为0}},actions: {addProductToCart(product: IProduct) {console.log(product)// 看商品有没有库存if (product.inventory < 1) {return}// 检查购物车中是否已有该商品const cartItem = this.cartProducts.find(item => item.id === product.id)// 如果有则让商品的数量 + 1if (cartItem) {cartItem.quantity++} else {// 如果没有则添加到购物车列表中this.cartProducts.push({id: product.id,title: product.title,price: product.price,quantity: 1 // 第一次添加数量是1 })}// 更新库存const prostore = useProductsStore()prostore.decrementProduct(product)},async checkout() {const res = await buyProducts()this.checkStatus = res ? '成功' : '失败'}}
})

http://www.ppmy.cn/news/144669.html

相关文章

看做马桶的如何搞企业内部协同——日企TOTO访谈记

同事都说我采访了一个做马桶的&#xff0c;尽管我反复强调是“卫浴产品”&#xff0c;哈哈。 但是经过和嘉宾聊了以后&#xff0c;才知道日企里做事真难&#xff01;&#xff01; 摸准脉门 日企空降CIO如何安全着陆 作为IT管理者&#xff0c;虽然承担着TOTO上海分公司信息化建设…

B树(C语言描述)

一.概念 B树是一种多路平衡查找树&#xff0c;不同于二叉平衡树&#xff0c;他不只是有两个分支&#xff0c;而是有多个分支&#xff0c;一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树&#xff0c;B树用于磁盘寻址&#xff0c;它是一种高效的查找算法。 二.性质…

tcpdump 抓包工具详细图文教程(下)

目录 一、tcpdump 常用参数的使用 1.1 tcpdump -i # 指定监听网络接口 1.2 tcpdump -w # 将捕获到的信息保存到文件中&#xff0c;且不分析和打印在屏幕 1.3 tcpdump -r # 从文件中读取数据 1.4 tcpdump -n # 不把 ip 转化成域名 1.5 tcpdump -t # 在每行的输出中不…

9 概率图模型【手写笔记】

文章目录 9 概率图模型【手写笔记】9.1 背景介绍9.2 贝叶斯网络&#xff08;Bayesian Network&#xff09;——有向图网络9.3 马尔可夫网络&#xff08;Markov Network&#xff09;——无向图网络9.4 Inferce&#xff08;推断&#xff09;——求解后验9.5 更多的图的概念 9 概率…

一文简述低代码到底是什么?

在进入正文之前&#xff0c;有必要给大家拨正一个误区&#xff1a; “开发≠写代码” 由于现在低代码&零代码产品在宣传过程中着重强调“公民开发”这一概念&#xff0c;我们随便点开一篇相关文章章&#xff0c;必定会有一句&#xff1a;“人人都是开发者&#xff0c;无需…

强排式热水器坏了

中台-品保 2022年09月28日 星期三 09:00会议号&#xff1a; 996 414 817密码&#xff1a; 123456https://wbxlogin02.foxconn.com/orion/joinmeeting.do?MTIDmcc6b7611a8038385bd7356c2d002629e

华帝股份的一些看法

华帝属于在厨电板块排名第三的股票了 紧随老板和方太之后 但营业收入方面其实差距不大(参考19年报老板电器77.61亿 华帝股份57.48亿) 然华帝和老板的市值却差距明显(老板电器最新市值403亿 华帝股份82亿) 老板电器的市值是华帝股份的5倍 参考老板电器 华帝的市值在300亿比较合适…

终于换热水器了。

好不容易&#xff0c;说是要换热水器了。差不多等了一下午。 开始&#xff0c;liuz 说是要 18 以后。于是&#xff0c;下午先去了公司&#xff0c;整一个 2百多万条记录的分层筛选。刚到公司&#xff0c;装热水器的就来了电话。说是要过去。一时偷懒&#xff0c;让他到了再给咱…