npm i pinia -S
main.ts
// vue3 版本api
import { createPinia } from 'pinia'
// 返回一个vue插件
const store = createPinia()
// 使用pinia插件
app.use(store)
store
是一个用reactive
包裹的对象import { defineStore } from 'pinia'
// defineStore('user', ...) 和下面的形式相同
export const useUserStore = defineStore({
id: 'user',
state: () => ({
userid: localStorage.getItem('userid') || '',
}),
actions: {
setUserId(payload: string) {
this.userid = payload
}
}
})
const login = (): Promise<string> => {
return new Promise(resolve => {
setTimeout(() => {
resolve('userid')
}, 2000);
})
}
// defineStore('user', ...) 和下面的形式相同
export const useUserStore = defineStore({
id: 'user',
state: () => ({
userid: localStorage.getItem('userid') || '',
}),
actions: {
// 同步actions
setUserId(payload: string) {
console.log(payload)
this.userid = payload
},
// 异步actions
async getUser() {
// actions可以互相调用
this.setUserId(await login())
}
}
})
actions: {
// 在同步actions中调用异步actions
setUserId(payload: string) {
console.log(payload)
this.getUser()
},
async getUser() {
// this.setUserId(await login())
this.userid = await login()
}
}
相当于组件中的computed也具有缓存
接收"状态"作为第一个参数
state: () => ({
userid: localStorage.getItem('userid') || '',
counter: 0
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
this
的注意事项定义常规函数时可以通过 this
访问到 整个 store 的实例, 但是需要定义返回类型(在 TypeScript 中)。 这是由于 TypeScript 中的一个已知限制,并且不会影响使用箭头函数定义的 getter,也不会影响不使用 this 的 getter:
export const useStore = defineStore('main', {
state: () => ({
counter: 0,
}),
getters: {
// 自动将返回类型推断为数字
doubleCount(state) {
return state.counter * 2
},
// 返回类型必须明确设置
doublePlusOne(): number {
// 调用其他getter:
return this.doubleCount + 1
// 等同于:
return this.counter * 2 + 1
},
},
})
Getters 只是幕后的 computed 属性,因此无法向它们传递任何参数。 但是,您可以从 getter 返回一个函数以接受任何参数:
这种操作getter不再缓存,只相当于在调用函数(从store 的解构中可以看出)
export const useStore = defineStore('main', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId)
},
},
})
组件
// store
getters: {
doubleCount: (state) => state.counter * 2,
doublePlusOne(): number {
// 等同于调用其他getter: return this.doubleCount + 1
return this.counter * 2 + 1
},
payloadCount() {
return (payload: number) => this.doublePlusOne + payload
}
},
// 组件
const { userid, payloadCount, } = storeToRefs(user)
模板
home: {{ user.userid }} {{ doubleCount }} {{ payloadCount(3) }}
$reset
重置状态
store.$reset()
$patch
派发actions
// 方式1:
user.$patch({userid: 'xxx'})
// 方式2:
cartStore.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
$state
访问 store 状态
store.$state = { counter: 666, name: 'Paimon' }
$subscribe
, 订阅变更
cartStore.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
// 与 cartStore.$id 相同
mutation.storeId // 'cart'
// 仅适用于 mutation.type === 'patch object'
mutation.payload // 补丁对象传递给 to cartStore.$patch()
// 每当它发生变化时,将整个状态持久化到本地存储
localStorage.setItem('cart', JSON.stringify(state))
})
// 可以利用该api针对某些 mutation.events.key 结合 localStorage 做判断实现数据持久化
user.$subscribe((mutation, state) => {
/**
* 下面是 mutation的属性
* key: "counter"
newValue: 1
oldValue: 0
target: {userid: 'userid', counter: 1}
type: "set"
oldTarget: undefined
*/
console.log('$%#', mutation.events as any, state)
})
$onAction
, 监听actions触发
可以利用after做一些事情
context.store.$onAction((arg) => {
// arg 属性
/**
* after: ƒ after(callback)
args: [] actions 参数
name: "setUserId"
onError: ƒ onError(callback)
store: action所在实例
*
*/
if(arg.name === '"setUserId"') {
console.log('onaction', arg)
arg.after(() =>{
// do something
})
}
})
createPinia()
创建的 piniacreateApp()
创建的当前应用程序(仅限 Vue 3)defineStore()
import type { PiniaPluginContext } from 'pinia'
// 持久化插件
export function persistencePlugin(context: PiniaPluginContext) {
/**
* key: "counter"
newValue: 1
oldValue: 0
target: {userid: 'userid', counter: 1}
type: "set"
oldTarget: undefined
*/
context.store.$subscribe((mutation: any) => {
if (mutation.storeId === 'user') {
if (mutation.events.key === 'userid') {
localStorage.setItem('userid', mutation.events.newValue)
}
}
})
/**
* after: ƒ after(callback)
args: [] actions 参数
name: "setUserId"
onError: ƒ onError(callback)
store: action所在实例
*
*/
context.store.$onAction((arg) => {
if (arg.name === '"setUserId"') {
console.log('onaction', arg)
}
})
}
1. npm i mockjs vite-plugin-mock
2.在vite.config.ts中加入配置
import { viteMockServe } from "vite-plugin-mock";
plugins: [
viteMockServe({
supportTs: true,
logger: false,
mockPath: "./mock/",
}),
],
3. 在根文件同等路径下去建立一个文件夹,取名mock.ts
4. 然后写入想要请求的接口的数据
export default [
{
url: "/api/banner/list",
method: "get",
response: () => {
return {
code: "200",
message: "获取成功",
data: [
{
img: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimages.uiiiuiii.com%2Fwp-content%2Fuploads%2F2019%2F07%2Fi-bn20190630-1-15.jpg&refer=http%3A%2F%2Fimages.uiiiuiii.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671816683&t=35a1fc5f8bd1483aa69fbd16dc7e7524",
alt: "112",
link: "112",
bannerid: "banner_6a1f7001-e580-4d8b-b5dd-7447f94c1990",
flag: true,
},
{
img: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01f6ad5dde2b7ca80120686b55f619.jpg%3Fx-oss-process%3Dimage%2Fauto-orient%2C1%2Fresize%2Cm_lfit%2Cw_1280%2Climit_1%2Fsharpen%2C100&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671816683&t=a4402cf070e22b867a74cc0d23a8c4e7",
alt: "1123",
link: "1123",
bannerid: "banner_35f7aa34-6745-4f88-934b-7b506330a695",
flag: true,
},
{
img: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F013aa3594fac92a8012193a3cabdb4.jpg&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671816683&t=0009e5acc265a854d79350e84b9cbb2a",
alt: "11234",
link: "11234",
bannerid: "banner_52cd31c3-7811-461c-9f1a-239845ab0578",
flag: true,
},
{
img: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F0183245697b4f66ac725af23df2dcc.jpg&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671816683&t=c60c7fb9f4d4935208407b8c8e874c74",
alt: "112345",
link: "112345",
bannerid: "banner_1ba6cee8-d2de-47c2-955b-cd5c773f6d70",
flag: true,
},
],
};
},
},
];