点击在线浏览,体验更好 | 链接 |
---|---|
古代JavaScript高级小册 | 链接 |
深入浅出Dart | 链接 |
古代TypeScript高级小册 | 链接 |
linwu的算法笔记 | 链接 |
Pinia 是 Vue.js 官网举荐的新一代状态治理库,它提供了十分简洁和直观的 API,能够极大地提高咱们治理利用状态的效率。本文将深刻介绍 Pinia 的各种高级用法,内容涵盖:
Pinia 的劣势
相比 Vuex,Pinia 有以下长处:
- 更贴合 Vue 3 的 Composition API 格调,学习老本更低
- 不须要辨别 Mutation 和 Action,对立应用 Actions 操作状态
- 反对 TypeScript,能够充分利用 TS 的动态类型零碎
- 模块化治理 States,每个模块是一个 Store
- 直观的 Devtools,能够看到每个 State 的变动
创立 Pinia
在 main.js 中导入 createPinia 并应用:
import { createApp } from 'vue'import { createPinia } from 'pinia'const pinia = createPinia()const app = createApp(App)app.use(pinia)
能够通过 app.config.globalProperties.$pinia
拜访 Pinia 实例。
Option Store
与 Vue 的选项式 API 相似,咱们也能够传入一个带有state
、actions
与getters
属性的 Option 对象(废除了Mutations)
应用 defineStore
API 定义 Store:
import { defineStore } from 'pinia'export const useMainStore = defineStore('main', { // state state: () => { return { counter: 0 } }, // getters getters: { doubleCount(state) { return state.counter * 2 } }, // actions actions: { increment() { this.counter++ } }})
- 接管惟一 ID 作为第一个参数
- state、getters、actions 定义形式与 Vue 组件相似
- 能够间接通过
this
拜访状态
Pinia 提供多种选项配置 Store:
state
定义响应式状态:
state: () => { return { count: 0 }}
必须是一个返回状态对象的函数。
getters
定义 getter 计算属性:
getters: { double(state) { return state.count * 2 }}
getter 能够接管参数:
getters: { getMessage(state) { return (name = 'Vue') => `Hello ${name}` }}
actions
定义方法批改状态:
actions: { increment(amount = 1) { this.count += amount }}
actions 反对同步和异步操作。
persist
配置数据长久化,须要应用插件:
persist: { enabled: true, strategies: [ { key: 'my_store', storage: localStorage, }, ]}
应用 Store
通过 useXxxStore()
获取 Store 实例:
import { useMainStore } from '@/stores/main'export default { setup() { const main = useMainStore() main.increment() } }
读取状态、调用 actions 同 Vue 组件。
读取状态
// 间接读取const count = main.count// 通过计算属性const double = computed(() => main.doubleCount)// 通过 storeToRefsconst { count } = storeToRefs(main)
调用 Actions
main.increment()const message = main.getMessage('Vue')
多个 Store
能够拆分多个 Store 治理不同模块状态:
stores|- user.js|- product.js
独自导出每个 Store 并在组件中应用:
import { useUserStore } from '@/stores/user'import { useProductStore } from '@/stores/product' export default { setup() { // ... }}
Store 能够相互援用:
// userStore.jsimport { useProductStore } from './product'export const useUserStore = defineStore({ // 能够间接应用 productStore})
Setup Store
集体比拟偏向这种语法
也存在另一种定义 store 的可用语法。与 Vue 组合式 API 的 setup 函数 类似,咱们能够传入一个函数,该函数定义了一些响应式属性和办法,并且返回一个带有咱们想裸露进来的属性和办法的对象。
export const useCounterStore = defineStore('counter', () => { const count = ref(0) function increment() { count.value++ } return { count, increment }})
在 Setup Store 中:
ref()
就是state
属性computed()
就是getters
function()
就是actions
Setup store 比 Option Store 带来了更多的灵活性,因为你能够在一个 store 内创立侦听器,并自在地应用任何组合式函数。不过,请记住,应用组合式函数会让 SSR 变得更加简单。
数据长久化
Pinia 默认状态不长久化,能够通过插件实现长久化:
npm install pinia-plugin-persistedstate
import persistedState from 'pinia-plugin-persistedstate'const pinia = createPinia()pinia.use(persistedState)
在 Store 中配置 persist
:
export const useUserStore = defineStore({ persist: { enabled: true } })
配置 storage
指定存储地位:
persist: { storage: sessionStorage}
Pinia 插件
Pinia 生态已有许多插件,能够扩大更多功能:
pinia-plugin-persistedstate
:数据长久化pinia-plugin-debounce
:防抖批改状态pinia-plugin-pinia-observable
:转换成 Observable
应用插件:
import piniaPluginPersist from 'pinia-plugin-persist'pinia.use(piniaPluginPersist)
Devtools
Pinia反对Vue devtools
购物车示例
咱们来通过一个购物车的例子看看 Pinia 的用法:
// store.jsimport { defineStore } from 'pinia'export const useCartStore = defineStore('cart', { state: () => { return { items: [] } }, getters: { total(state) { return state.items.reduce((total, item) => { return total + item.price }, 0) } }, actions: { addItem(item) { this.items.push(item) }, removeItem(id) { this.items = this.items.filter(i => i.id !== id) } }})
在组件中应用:
// Cart.vueimport { useCartStore } from '@/stores/cart'setup() { const cart = useCartStore() return { items: cart.items, total: cart.total }}
能够看出代码十分简洁直观。
Pinia 插件
Pinia 插件是一个函数,能够选择性地返回要增加到 store 的属性。它接管一个可选参数,即 context。
export function myPiniaPlugin(context) { context.pinia // 用 `createPinia()` 创立的 pinia。 context.app // 用 `createApp()` 创立的以后利用(仅 Vue 3)。 context.store // 该插件想扩大的 store context.options // 定义传给 `defineStore()` 的 store 的可选对象。 // ...}
而后用 pinia.use()
将这个函数传给 pinia
:
pinia.use(myPiniaPlugin)
插件只会利用于在 pinia
传递给利用后创立的 store,否则它们不会失效。
实现一个长久化插件
getStorage
函数:依据提供的key
从本地存储中读取数据。如果数据无奈解析或不存在,则返回null
。setStorage
函数:将提供的值转换为 JSON 格局,并以指定的key
保留到本地存储中。DEFAULT_KEY
常量:示意默认的本地存储键名前缀。如果在选项中未提供自定义键名,将应用该默认键名。Options
类型:定义了插件选项对象的类型,蕴含key
(本地存储键名前缀)和needKeepIds
(须要进行长久化的 Pinia 存储的 ID 数组)两个可选属性。- piniaPlugin` 函数:这是次要的插件函数,它接管一个选项对象,并返回一个用于解决 Pinia 存储的函数。
import { PiniaPluginContext } from "pinia";import { toRaw } from "vue";// Get data from local storage by keyexport function getStorage(key) { const data = localStorage.getItem(key); try { return JSON.parse(data); } catch (error) { return null; }}// Set data to local storage with a keyexport function setStorage(key, value) { const data = JSON.stringify(value); localStorage.setItem(key, data);}const DEFAULT_KEY = "pinia";type Options = { key?: string; needKeepIds?: string[];};const piniaPlugin = ({ key = DEFAULT_KEY, needKeepIds = [] }: Options) => { return (context: PiniaPluginContext) => { const { store } = context; const data = getStorage(`${key}-${store.$id}`); const subscribeToStore = () => { if (needKeepIds.length === 0 || needKeepIds.includes(store.$id)) { setStorage(`${key}-${store.$id}`, toRaw(store.$state)); } }; store.$subscribe(subscribeToStore); return { ...data, }; };};export default piniaPlugin;
图解算法小册
最近整顿了一本算法小册,感兴趣的同学能够加我微信linwu-hi
进行获取