pinia学习笔记
1、創建項目(vite+vue+ts)
pnpm create vite2、安裝pinia
yarn add pinia3、使用
1、引入注冊main.ts
import { createApp } from 'vue' import App from './App.vue' import { createPinia } from 'pinia' const pinia = createPinia() const app=createApp(App) app.use(pinia).mount('#app')2、初始化倉庫Store(存儲是使用定義的defineStore(),并且它需要一個唯一的名稱,作為第一個參數傳遞)
新建store/main.ts
import { defineStore } from 'pinia'export const mainStore = defineStore('main',{state:()=>{return {count:100,price:250}},getters:{doubleCount():number{return this.count*2},doublePrice():number{return this.price*2}},actions:{changeStoreData(){this.count+=1this.price+=1},} })3、頁面使用
?
?
<script setup lang="ts"> import { ref } from 'vue' import { storeToRefs } from 'pinia'; import { mainStore } from '../store/main'; const store = mainStore() let { count,doubleCount,price,doublePrice } = storeToRefs(store) defineProps<{ msg: string }>() const changeData = ()=>{//1、直接修改count// count.value++// price.value++//2、$patch批量修改State的值// store.$patch({// count:500,// price:1000// })//3、$patch批量修改函數形式// store.$patch((state)=>{// state.count++// state.price++// })//4、通過原始對象修改整個實例//$state您可以通過將store的屬性設置為新對象來替換store的整個狀態//缺點就是必須修改整個對象的所有屬性// store.$state={// count:0,// price:1// }//5、通過actions修改store.changeStoreData()}</script> <template><h1>{{ msg }}</h1><h1>數量</h1><h2>pinia-count數據{{count}}</h2><h3>pinia- getters-2倍數量{{doubleCount}}</h3><h1>價格</h1><h2>pinia-price數據{{price}}</h2><h3>pinia- getters-2倍價格{{doublePrice}}</h3><el-button size='large' type="primary" @click="changeData">改變數據</el-button> </template><style scoped></style>4、actions(異步及調用其他actions方法)?
新建store/use.ts模塊
import { defineStore } from 'pinia' import { ElLoading } from 'element-plus' type Res = {nickname:string,age:number } const Login = ()=>{return new Promise<Res>((resolve,reject)=>{const loading = ElLoading.service({lock: true,text: 'Loading',background: 'rgba(0, 0, 0, 0.7)',})setTimeout(() => {resolve({nickname:'張三',age:22})loading.close()}, 5000);}) } export const userStore = defineStore('user',{state:()=>{return {nickname:'',age:0}},getters:{},actions:{async getUserInfo(){const res = await Login();this.nickname=res.nickname;//this.age=res.age;//調用其他actionsthis.setAge(res.age)},setAge(age:number){this.age=age}} }) <template><h1>用戶組件</h1><h2>昵稱{{nickname}}--年齡{{age}}</h2><el-button type="primary" size="large" @click="getUserInfo">獲取用戶信息</el-button></template> <script setup lang='ts'> import { ref,reactive} from 'vue' import { userStore } from '../store/user'; import { storeToRefs } from 'pinia'; const user = userStore() let {nickname,age} = storeToRefs(user) const getUserInfo = ()=>{user.getUserInfo() } </script> <style lang='scss' scoped> </style>5、getters?(主要作用類似于computed 數據修飾并且有緩存)
getters 可以互相調用?普通函數形式可以使用this?使用箭頭函數不能使用this this指向已經改變指向undefined 修改值請用state
getters:{doubleCount():number{//return this.count*2return this.doublePrice*2},doublePrice:(state)=>state.price*2},6、 常用api
1、$reset(重置store到他的初始狀態)
<el-button size='large' type="primary" @click="resetData">重置數據</el-button> const resetData =()=>{main.$reset() }?2、訂閱state改變(類似于Vuex 的abscribe? 只要有state 的變化就會走這個函數)
main.$subscribe((args,state)=>{console.log(args,state,'數據改變') })第二個參數
如果你的組件卸載之后還想繼續調用請設置第二個參數
main.$subscribe((args,state)=>{console.log(args,state,'數據改變') },{detached:true })3、訂閱Actions的調用(只要有actions被調用就會走這個函數)
main.$onAction((args)=>{console.log(args,'action調用'); })7、 pinia插件 --數據持久化
1、安裝
cnpm i pinia-plugin-persist --save2、新建store/index.ts
import { createPinia } from 'pinia' //pinia 持久化插件 import piniaPluginPersist from 'pinia-plugin-persist' const store = createPinia() store.use(piniaPluginPersist) export default store3、修改main.ts
import { createApp } from 'vue' import App from './App.vue'import 'element-plus/dist/index.css' import store from './store/index'; import piniaPluginPersist from 'pinia-plugin-persist'; store.use(piniaPluginPersist) const app=createApp(App) app.use(store).mount('#app')4、保存nickname,修改store/user.ts
import { defineStore } from 'pinia' import { ElLoading } from 'element-plus' type Res = {nickname:string,age:number } const Login = ()=>{return new Promise<Res>((resolve,reject)=>{const loading = ElLoading.service({lock: true,text: 'Loading',background: 'rgba(0, 0, 0, 0.7)',})setTimeout(() => {resolve({nickname:'張三',age:22})loading.close()}, 5000);}) } export const userStore = defineStore('user',{state:()=>{return {nickname:'',age:0}},getters:{},actions:{async getUserInfo(){const res = await Login();this.nickname=res.nickname;//this.age=res.age;//調用其他actionsthis.setAge(res.age)},setAge(age:number){this.age=age}},persist:{enabled:true,strategies:[{storage:localStorage,paths:['nickname']}]} })?4、購物車案例
?
1、新建src/api/shop.ts
/*** src/api/shop.ts* Mocking client-server processing*/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: 'H&M 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(1000)return _products}export const buyProducts = async () => {await wait(1000)return Math.random() > 0.5}/*** 封裝了Promise版本的定時器* @param delay 延遲時間* @returns Promise*/async function wait(delay:number) {return new Promise(resolve => setTimeout(resolve, delay))}2、新建components/ProductList.vue
<template><ul><li class="item" v-for="item in productsStore.all"><div class="title">商品名稱:{{item.title}}</div>--<div class="price">商品價格:{{item.price}}</div><div class="price">商品庫存:{{item.inventory}}</div><el-button type="primary" :disabled="!item.inventory" @click="cartStore.addProductToCart(item)">添加到購物車</el-button></li></ul> </template><script lang="ts" setup> import { useCartStore } from '../store/cart'; import { useProdunctsStore } from '../store/products'const productsStore = useProdunctsStore() const cartStore = useCartStore()productsStore.loadAllProducts() // 加載所有數據 </script> <style lang="scss" scoped> .item{display: flex;align-items: center;justify-content: center;.title{margin: 0 15px;}.price{margin: 0 15px;} } </style>3、新建components/Cart.vue
<template><div class="cart"><h2>我的購物車</h2><ul v-if="cartProducts&&cartProducts.length>0"><li v-for="item in cartProducts">商品名稱:=:{{ item.title }} - 商品價格:{{ item.price }} × 商品數量:{{ item.num }}</li></ul><p v-else><i>請添加一些商品到購物車</i></p><p>商品總價: {{ totalPrice }}</p></div> </template><script lang="ts" setup> import { useCartStore } from '../store/cart' import { storeToRefs } from 'pinia'; const cartStore = useCartStore() let { cartProducts,totalPrice } = storeToRefs(cartStore) </script>4、組件在App.vue中引用
<script setup lang="ts"> import ProductList from './components/ProductList.vue'; import Cart from './components/Cart.vue'; </script><template><ProductList /><hr><Cart /> </template><style> #app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px; } ul li{list-style: none;line-height: 50px; } </style>5、新建store/products.ts
import { defineStore } from "pinia" import { getProducts, IProduct } from "../api/shop"export const useProdunctsStore = defineStore('products', {state: () => {return {all: [] as IProduct[] // 所有商品列表(學習類型斷言的使用)}},getters: {}, actions: {//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--}}} })6、新建store/cart.ts
import { defineStore } from "pinia"; import { buyProducts, IProduct } from "../api/shop"; import { useProdunctsStore } from "./products";/*** {id, title, price, quantity}*/ type CartProduct = { // 合并num: number } & Omit<IProduct, 'inventory'> // Omit是過濾export const useCartStore = defineStore('cart', {state: () => {return {cartProducts: [] as CartProduct[],checkoutStatus: null as null | string}},getters: {// 總價totalPrice(state) {return state.cartProducts.reduce((total, item) => {return total + item.price * item.num}, 0)}},actions: {/*** 往購物車添加商品* 這是一個相對復雜的邏輯,與容器中的數據強相關,所以肯定要定義在actions里面!* @param product 需要添加的商品*/addProductToCart(product: IProduct) {// 先看商品有沒有庫存if (product.inventory <= 0) {return}// 檢查購物車中是否已有該商品const cartItem = this.cartProducts.find(item => item.id === product.id)// 如果有則讓商品數量+1if (cartItem) {cartItem.num++} else {// 如果沒有則添加到購物車列表中this.cartProducts.push({id: product.id,title: product.title,price: product.price,num: 1})}// 跟新商品庫存(應該由商品容器暴露API)const productsStore = useProdunctsStore()productsStore.decrementProduct(product)// 跨容器通信!!!!!竟然如此簡單!!!},/*** 結算*/async checkOut() {const ret = await buyProducts() this.checkoutStatus = ret ? '成功' : '失敗'if (ret) {this.cartProducts = [] // 清空購物車}}} })總結
- 上一篇: 织梦图集php,dedecms织梦文章模
- 下一篇: 确保已在无线网络上启用dhcp服务器,启