Pinia 系统学习

  • Pinia

    • 初衷设计

      • 设计一个拥有组合式API的Vue状态管理库

    • 优势

      • Devtools支持

      • 热更新

      • 插件:可通过插件扩展Pinia功能

      • 提供TypeScript支持以及自动功能补全

      • 支持服务端渲染

    • 核心概念

      • 定义Store

        • defineStore import {defineStore} from 'pinia'

          • defineStore(arg1, options)

          • arg1: 名字,同时也被用作id,required,id将被用作连接store和devtools

          • options: 接受两类值:Setup函数 或者 Option对象

            • Opition对象 { state: {}, getters: {}, actions: {} }

            • Setup函数: 类似Vue setup函数 () => { return { ...props } } 其中: ref()就是state属性 computed()就是getters function() 就是actions 注意:不能在store中使用私有属性,因为必须返回state属性pinia才能正确是识别state

              • store是一个用reactive包装的对象。不能对它进行解构,结构会失去响应性的连接

              • 解决办法:使用 storeToRefs() import { storeToRefs } from 'pinia' const store = userCounterStore() const { name, doubleCount } = storeToRefs(store) 对应action的方法可以直接解构 const { increment } = store

      • State const store = useStore() const count = store.count

        • 在Pinia中, state被定义为一个返回初始状态的函数。推荐使用箭头函数,获取完整类型推理

        • TypeScript支持

        • 访问state const state = store.state

        • 重置state

          • 使用选项时API store.$reset() 将store重置为初始值

            • 辅助函数:mapState / mapWrittableState

            • import { mapState } from 'pinia' 通过mapState可以state属性映射为 只读的计算属性

            • impor { mapWrittableState } from 'pinia' 映射为一个可以修改的属性 computed { ... mapWrittableState(useCounterStore, ['count]) ...mapWrittableState(useCounterStore, { myOwnName: 'count' } }

            • mapWrittable 不能像 mapstate 传递一个函数

          • 在Setup Store中,需要创建自己的$reset()方法 export const useCounterStore = defineStore('counter', () => { const count = ref(0) function $reset() { count.value = 0 } return { count, $reset } })

        • 变更state

          • 直接修改属性:store.count = 1

          • $patch在同一时间修改多个属性,接受一个state的补丁对象 store.$patch({ count: store.count + 1, age: 120, name: 'DIO' })

          • $patch接受一个函数修改多个属性 store.$path(() =>{ state.item.push({ name: 'shoes', quantity: 1 }) state.hasChange = true })

        • 替换state

          • 使用$patch()替换state对象 store.$patch({count: 24}) store.$state = { count: 24 } 实际并没有替换$state 不能完全替换掉store的state,这样会破坏其响应性

        • 订阅state

          • 可以使用store.$subscribe() 方法侦听state及其变化。 store.$subscribe((mutation, type) => { mutation.type // direct | patch object / patch function mutation.storeId // 注册的store的name mutation.payload // 传递给store.$patch()的补丁对象 // 每当状态发生变化时,将整个state持久化道本地 localStorage.setItem('car', JSON.stringify(state)) })

          • 默认情况下,state subscription 会被绑定到添加他们的组件上,组件卸载时会被自定删除 问题解决:可以通过$subscribe(callbakc, {detached: true})的第二个参数 detached设置为true, 可以将subcription 从当前组件分离,组件卸载之后然后会被保留

          • 可以使用pinia实例上使用watch()监听整个state watch( pinia.state, (state) => { localStorage.setItem('piniaState', JSON.stringify(state) }, {deep: true} )

      • Getter const store = useStore() store.getterProp

        • Getter完全等同于store的state的计算值。通过defineStore() 的 getters属性定义。 推荐使用➡️箭头函数,接收 state 作为第一个参数

        • 访问其他的Getter 可以通过 this 访问到整个 store 实例, 但必须定义返回类型(在TypeScript中) export const useCounterStore = defineStore({ state: () => ({ count: 0 }), getters: { doubleCount(state) { return state.count * 2 }, doublePlusOne(): number { return this.doubleCount + 1 } } })

        • 向Getter传递参数 可以从Getter返回一个函数,从而解决不能传递参数的问题 可以在getter 本身中缓存一些结果 解决 getter被调用后getter将不在被缓存的问题

        • 访问其他store的getter 可以直接在Getter中使用 import { useOtherStore } from './other-store' export const useStore = defineStore('main', { state: () => ({ // ... }), getters: { otherGetter(state) { const otherStore = useOtherStore() return state.localData + otherStore.data }, }, })

        • 使用setup() 时的用法 作为store的一个属性,可以直接访问任何getter和state

        • 使用选项时API 可以通过在setup() 中使用 可以通过辅助函数mapState() 函数来映射getters

      • Action const store = useStore() const actionProp = store.actionProp

        • Action 相当于组件中method。 通过defineStore() 中的 actions 属性定义。 是定义业务逻辑的完美选择 action 可以 通过 this 访问整个 store 实例 action 可以时异步的 action 可以像函数或者通常意义上的方法一样被调用

        • 访问其他store的action 直接引入store,然后在 action 中直接调用即可

        • 使用选项式API的用法 使用setup() 不使用setup(), 可以使用辅助函数 mapActions() ,将 action 映射为对应组件中的方法

        • 订阅action 可以通过 store.$onAction() 监听 action 和 它们的结果 传递给$onAction(callback, false)函数的回调函数 是在action本身之前执行 callback: () => { after(() => {}) onError((error) => {}) } after() ,表示在promise解决之后执行,即在action解决之后执行一个回调函数 onError(), 表示在action抛出错误或reject时执行一个回调函数 action 订阅器会被绑定到添加它们的组件上(如果store在组件的 setup()内)。则组件卸载时,它们将会被自动删除。 若需要保留,则将第二个参数设置为true, 以便将其从当前组件中分离。

      • 插件

        • 插件是一个函数,可以选择性的返回要添加到store 的属性。 接收一个参数,即context context { pinia // 用creatPinia()创建的 pinia app // 用createApp()创建的当前应用 store // 插件想扩展的 store options // 定义传给 defineStore() 的 store 的 可选对象 } 注意: 1. 每个 store 都被 reactive 包装过,所以可以自动解包任何包含的Ref(ref( ) / computed() ...) 2. 插件中,state 变更和添加都是发生在 store 被激活之前, 因此不会触发任何订阅函数 然后使用pinia.use(myPiniaPlugin)

        • 扩展Store 返回特定属性的对象 为 每个store 添加特定的属性 pinia.use( () => { hello: 'world' })

        • 添加新的state, 需要同时在两个地方添加 1. 在 store 上添加自定义属性 2. 在 store.$state上添加自定义属性 添加新的外部属性 先用 markRaw()包装,在传递给pinia import { markRaw } from 'vue' impor { router } from './router' pinia.use(({ store }) => { store.router = markRaw(router) } )

        • 直接在store上设置属性 pinia.use(({ store }) => { store.hello = 'world' })

        • 在devtools中调试, 为追踪到添加的自定义属性,在dev开发模式下需要添加到 store._customProperties中 pinia.use(({ store }) => { store.hello = 'world' if (process.env.NODE_ENV === 'development') { store._customProperties.add('hello') } })

        • 在插件中调用 $subscribe 可以在插件中调用store.$subscrbe , store.$onAction 添加新的选项, 在定义store 时, 可以创建新的选项,以便在插件中使用它们

      • 组件外的Store

        • 在用 app.use(pinia) 安装 pinia 插件后,对 useStore() 的任何调用都会正常执行:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值