1. 安装
npm install pinia
2. 创建status
// 1.引入
import { defineStore, storeToRefs, mapState, mapActions, } from 'pinia'
export const useAlertsStore = defineStore('alerts', {
// 其他配置...
})
// 2. 三个基本概念 state getters actions 对应 data computed methods
// 2.1 如果使用 函数返回值的方式
// 2.1.1 定义变量 const count = ref(0)
// 2.1.2 定义计算属性 const doubleCount = computed(()=> count.value * 2)
// 2.1.3 定义方法 function increment() {count++}
// 2.1.4 最终 通过return {} 的形式将定义的方式送出去
// 3 对于结构 如果使用对象解构state 热需要额外引入storeToRefs 方法不受影响;也可以直接通过 . 的形式
// 4 如果使用vue2 使用Vue.set() ???
// 5 可以直接引入 像是vuex 一样 放在 computed 里面
// 5.1 引入 mapState 然后引入store 文件暴露出来的对象...mapState(useCounterStore, ['count'])
// 5.2 想要把引入的变量 改名字 则需要 换成对象引入 ...mapWritableState(useCounterStore, {
myOwnName: 'count',
}),
修改状态的值
// 1 使用 $patch 可以同时修改多个值
store.$patch({
count: store.count + 1,
age: 120,
name: 'DIO',
})
// 2 如果想进行比较复杂的变化 则可以换成 函数
store.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
// 3 整体改变 state 就直接用 $patch 给个新的对象就可以
订阅 修改变化
// 1. subscribe 相当于计算属性
cartStore.$subscribe((mutation, state) => {
// 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('cart', JSON.stringify(state))
})
// 2. 如果想 在组件卸载以后 依然保持相应 那么需要增加第二个配置项
const someStore = useSomeStore()
// 此订阅器即便在组件卸载之后仍会被保留
someStore.$subscribe(callback, { detached: true })
// 3. 侦听器 在pinia 实例上 使用 watch() 函数 监听整个 state
watch(
pinia.state,
(state) => {
// 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('piniaState', JSON.stringify(state))
},
{ deep: true }
)
// 4. 当个变量侦听???
// 5. watch() 放在什么地方
getters 传递参数
// 1 不支持传递参数
// 2 可以让 getters 返回一个函数 然后就可以在使用的时候传递参数
<script setup>
import { useUserListStore } from './store'
const userList = useUserListStore()
const { getUserById } = storeToRefs(userList)
// 请注意,你需要使用 `getUserById.value` 来访问
// <script setup> 中的函数
</script>
<template>
<p>User 2: {{ getUserById(2) }}</p>
</template>
// 3 访问其他store的getter 直接用getters中的state 访问就可以
action
// 1 使用 store.$onAction() 监听异步返回结果
const unsubscribe = someStore.$onAction(
({
name, // action 名称
store, // store 实例,类似 `someStore`
args, // 传递给 action 的参数数组
after, // 在 action 返回或解决后的钩子
onError, // action 抛出或拒绝的钩子
}) => {
// 为这个特定的 action 调用提供一个共享变量
const startTime = Date.now()
// 这将在执行 "store "的 action 之前触发。
console.log(`Start "${name}" with params [${args.join(', ')}].`)
// 这将在 action 成功并完全运行后触发。
// 它等待着任何返回的 promise
after((result) => {
console.log(
`Finished "${name}" after ${
Date.now() - startTime
}ms.\nResult: ${result}.`
)
})
// 如果 action 抛出或返回一个拒绝的 promise,这将触发
onError((error) => {
console.warn(
`Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
)
})
}
)
// 手动删除监听器
unsubscribe()
// 2 同样如果不想被清理 则 增加一个参数
someStore.$onAction(callback, true)
插件 相当于初始化 或者全局创建的时候 使用 平时不能使用
import { createPinia } from 'pinia'
// 1 插件使用 pinia.use() 添加到pinia实例
// 2 pinia实例 pinia = createPinia()
// 3 添加后 传递给应用创建的store上面就都有了
// 4 如果是在vue2 使用那么创建属性的时候 需要用 Vue.set() 或者装 @vue/composition-api 然后用 set()
import { set, toRef } from '@vue/composition-api'
pinia.use(({ store }) => {
if (!Object.prototype.hasOwnProperty(store.$state, 'hello')) {
const secretRef = ref('secret')
// 如果这些数据是要在 SSR 过程中使用的
// 你应该将其设置在 `$state' 属性上
// 这样它就会被序列化并在激活过程中被接收
set(store.$state, 'secret', secretRef)
// 直接在 store 里设置,这样你就可以访问它了。
// 两种方式都可以:`store.$state.secret` / `store.secret`。
set(store, 'secret', secretRef)
store.secret // 'secret'
}
})
// 4. 如果添加的是外部属性 之类的 那么需要先用 markRaw() 包装一下
import { markRaw } from 'vue'
// 根据你的路由器的位置来调整
import { router } from './router'
pinia.use(({ store }) => {
store.router = markRaw(router)
})
// 5 全局监听 或者 全局监听异常
pinia.use(({ store }) => {
store.$subscribe(() => {
// 响应 store 变化
})
store.$onAction(() => {
// 响应 store actions
})
})
添加新的选项 感觉有用 暂时没想到应用场景 先直接copy
添加新的选项
在定义 store 时,可以创建新的选项,以便在插件中使用它们。例如,你可以创建一个 debounce 选项,允许你让任何 action 实现防抖。
js
defineStore('search', {
actions: {
searchContacts() {
// ...
},
},
// 这将在后面被一个插件读取
debounce: {
// 让 action searchContacts 防抖 300ms
searchContacts: 300,
},
})
然后,该插件可以读取该选项来包装 action,并替换原始 action:
js
// 使用任意防抖库
import debounce from 'lodash/debounce'
pinia.use(({ options, store }) => {
if (options.debounce) {
// 我们正在用新的 action 来覆盖这些 action
return Object.keys(options.debounce).reduce((debouncedActions, action) => {
debouncedActions[action] = debounce(
store[action],
options.debounce[action]
)
return debouncedActions
}, {})
}
})
注意,在使用 setup 语法时,自定义选项作为第 3 个参数传递:
js
defineStore(
'search',
() => {
// ...
},
{
// 这将在后面被一个插件读取
debounce: {
// 让 action searchContacts 防抖 300ms
searchContacts: 300,
},
}
)