背景

对于pinia的使用,可参考官方文档在这不做过多赘述。这边主要来讲讲pinia中 少用且好用的方法,为什么我们选择pinia而不用vuex

ps: 以下写法全部基于组合式API

使用方式:

先下载依赖

  npm i pinia -s

在vue3中,main.js这么写

  import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue' const pinia = createPinia()
const app = createApp(App) app.use(pinia)
app.mount('#app')

ps:就别考虑v2了吧,v2老老实实用vuex。

State

1、如何修改State

在传统的vuex中我们是不建议直接修改state的,而是要求我们通过mutation来修改state,但是在pinia中我们可以直接修改state。例如:

const store = useStore()

store.count++

如果我们需要在同一时间变更多个属性,可以通过$patch方法,例如:

store.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})

2、如何订阅State

用来监听state是否发生变化,与watch相比,使用 $subscribe() 的好处是 subscriptions 在 patch 后只触发一次 。例如

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 // 传递给 cartStore.$patch() 的补丁对象。 // 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('cart', JSON.stringify(state))
})

在组合式API中可以这么使用:

<script setup>
const someStore = useSomeStore()
// this subscription will be kept even after the component is unmounted
someStore.$subscribe(callback, { detached: true })
</script>

Getter

1、如何访问其他store 的 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 //otherStore.data 就是其他getter中的getter
},
},
})

2、如何像getter中传递参数

Getter 只是幕后的计算属性,所以不可以向它们传递任何参数。不过,你可以从 getter 返回一个函数,该函数可以接受任意参数,例如

export const useStore = defineStore('main', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId)
},
},
})

组件中使用:

<script setup>
import { useUserListStore } from './store'
const userList = useUserListStore()
const { getUserById } = storeToRefs(userList)
// note you will have to use `getUserById.value` to access
// the function within the <script setup>
</script> <template>
<p>User 2: {{ getUserById(2) }}</p>
</template>

ps: getter 将不再被缓存,它们只是一个被你调用的函数。不过,你可以在 getter 本身中缓存一些结果,虽然这种做法并不常见,但有证明表明它的性能会更好

Action

1、如何访问其他 store 的 action

举个:

  import { useAuthStore } from './auth-store'

export const useSettingsStore = defineStore('settings', {
state: () => ({
preferences: null,
// ...
}),
actions: {
async fetchUserPreferences() {
const auth = useAuthStore()
if (auth.isAuthenticated) {
this.preferences = await fetchPreferences() //这行用了别的store的action
} else {
throw new Error('User must be authenticated')
}
},
},
})

2、订阅 action

你可以通过 store.$onAction() 来监听 action 和它们的结果。传递给它的回调函数会在 action 本身之前执行。after 表示在 promise 解决之后,允许你在 action 解决后执行一个一个回调函数。同样地,onError 允许你在 action 抛出错误或 reject 时执行一个回调函数。这些函数对于追踪运行时错误非常有用,类似于Vue docs 中的这个提示。

这里有一个例子,在运行 action 之前以及 action resolve/reject 之后打印日志记录。

 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()

默认情况下,action 订阅器会被绑定到添加它们的组件上(如果 store 在组件的 setup() 内)。这意味着,当该组件被卸载时,它们将被自动删除。如果你想在组件卸载后依旧保留它们,请将 true 作为第二个参数传递给 action 订阅器,以便将其从当前组件中分离:

<script setup>
const someStore = useSomeStore()
// this subscription will be kept even after the component is unmounted
someStore.$onAction(callback, true)
</script>

ps:这部分没有亲自写过demo,直接照搬官方文档了

插件

1、介绍

由于有了底层 API 的支持,Pinia store 现在完全支持扩展。以下是你可以扩展的内容:

  • 为 store 添加新的属性
  • 定义 store 时增加新的选项
  • 为 store 增加新的方法
  • 包装现有的方法
  • 改变甚至取消 action
  • 实现副作用,如本地存储
  • 仅应用插件于特定 store

    插件是通过 pinia.use() 添加到 pinia 实例的。最简单的例子是通过返回一个对象将一个静态属性添加到所有 store。例如:
import { createPinia } from 'pinia'

// 创建的每个 store 中都会添加一个名为 `secret` 的属性。
// 在安装此插件后,插件可以保存在不同的文件中
function SecretPiniaPlugin() {
return { secret: 'the cake is a lie' }
} const pinia = createPinia()
// 将该插件交给 Pinia
pinia.use(SecretPiniaPlugin) // 在另一个文件中
const store = useStore()
store.secret // 'the cake is a lie'

这对添加全局对象很有用,如路由器、modal 或 toast 管理器。

2、如何拓展Store

为了能让devtools 自动追踪到,推荐使用下列方法:

  pinia.use(({ store }) => {
store.hello = 'world'
})

3、添加的属性在store中是共享还是独享,可以如下配置:

const sharedRef = ref('shared')
pinia.use(({ store }) => {
// 每个 store 都有单独的 `hello` 属性
store.hello = ref('secret')
// 它会被自动解包
store.hello // 'secret' // 所有的 store 都在共享 `shared` 属性的值
store.shared = sharedRef
store.shared // 'shared'
})

4、添加新的选项

在定义 store 时,可以创建新的选项,以便在插件中使用它们。例如,你可以创建一个 debounce 选项,允许你让任何 action 实现防抖。

defineStore('search', {
actions: {
searchContacts() {
// ...
},
}, // 这将在后面被一个插件读取
debounce: {
// 让 action searchContacts 防抖 300ms
searchContacts: 300,
},
})

然后,该插件可以读取该选项来包装 action,并替换原始 action:

// 使用任意防抖库
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 个参数传递:(前面举的例子都是 Option Store)

defineStore(
'search',
() => {
// ...
},
{
// 这将在后面被一个插件读取
debounce: {
// 让 action searchContacts 防抖 300ms
searchContacts: 300,
},
}
)

以下均为亲自写过demo,以后再补充吧

5、如何添加新的state

6、如何添加新的外部属性

7、在插件中调用 $subscribe

vue中新的状态管理器-pinia的更多相关文章

  1. vue状态管理器(用户登录简单应用)

    技术点:通过vue状态管理器,对已经登录的用户显示不同的页面: 一  vue之状态管理器应用 主要用来存储cookie信息 与vue-cookies一起使用 安装:npm install vue-co ...

  2. 对于React各种状态管理器的解读

    首先我们要先知道什么是状态管理器,这玩意是干啥的? 当我们在多个页面中使用到了相同的属性时就可以用到状态管理器,将这些状态存到外部的一个单独的文件中,不管在什么时候想使用都可以很方便的获取. reac ...

  3. VueX状态管理器 的应用

    VueX状态管理器 cnpm i vuex axios -S 1 创建Vuex 仓库 import Vue from 'vue' import Vuex from 'vuex' vue.use(Vue ...

  4. vue中怎样实现 路由拦截器

    vue中怎样实现 路由拦截器(当用户没有登录的时候,跳转到登录页面,已经登录的时候,不能跳转到登录页,除非后台token失效) 在 我们需要实现这样 一个功能,登录拦截 其实就是 路由拦截,首先在定义 ...

  5. VS2013中Nuget程序包管理器控制台使用入门(三)-项目实战(原创)

    VS2013中Nuget程序包管理器控制台使用入门(三)-项目实战 1.给指定项目安装Newtonsoft.Json ,Version 4.5.11 PM> Install-Package Ne ...

  6. PHP V5.2 中的新增功能,第 1 部分: 使用新的内存管理器

    PHP V5.2:开始 2006 年 11 月发布了 PHP V5.2,它包括许多新增功能和错误修正.它废止了 5.1 版并被推荐给所有 PHP V5 用户进行升级.我最喜欢的实验室环境 —— Win ...

  7. vue - 状态管理器 Vuex

    状态管理 vuex是一个专门为vue.js设计的集中式状态管理架构.状态?我把它理解为在data中的属性需要共享给其他vue组件使用的部分,就叫做状态.简单的说就是data中需要共用的属性.

  8. vue项目--vuex状态管理器

    本文取之官网和其他文章结合自己的理解用简单化的语言表达.用于自己的笔记记录,也希望能帮到其他小伙伴理解,学习更多的前端知识. Vuex 是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态 ...

  9. 轻量级状态管理库Pinia试吃

      最近连续看了几个GitHub上的开源项目,里面都用到了 Pinia 这个状态管理库,于是研究了一下,发现确实是个好东西!那么,Pinia 的特点: 轻量化 -- Pinia 体积约1KB,十分轻巧 ...

  10. TensorFlow中的显存管理器——BFC Allocator

    背景 作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 使用GPU训练时,一次训练任务无论是模型参数还是中间结果都需要占用大量显存.为了 ...

随机推荐

  1. hdu1710 二叉树(C/C++)

    hdu1710 题目地址:https://acm.dingbacode.com/showproblem.php?pid=1710 (最近几天杭电原网址开不进去了,之后应该可以通..吧) Binary ...

  2. python音乐分类--knn

    1 #利用knn算法分类音乐,将音乐进行情绪分类 2 #将音乐分为兴奋的(excited), 愤怒的(angry),悲伤的(sorrowful),轻松的(relaxed) 3 4 #可分离因素 5 # ...

  3. Navicat Premium 12 安装破解过程 (经过测试)

    @ 目录 下载安装 下载 解压文件目录 安装使用步骤截图 1. 安装navicat120_premium_cs_x64.exe 软件 2. 解压Navicat.Premium 破解补丁.rar 3. ...

  4. Java流程控制1

    Scanner对象 java.util.Scanner 通过Scanner类来获取用户输入 next()和nextline()来获取输入的字符串,读取前我们一般需要使用hasnext()和hasnex ...

  5. 服务器端口对外开放(包括,mysql,django)

    1.查看对外开放端口号,并开放端口 查看开放的端口 ,有两个命令 1.1.iptables -L -n (比较清晰明了) 1. 2.firewall-cmd --list-ports 1.3 .打开端 ...

  6. 为什么reids是单线程

    我们首先要明白,reids很快,官方表示,因为reids是基于内存的操作,cpu不是reids的瓶颈,redis的瓶颈有可能是机器内存的大小或者网络带宽,既然单线程容易控制,而且cpu不会成为瓶颈,所 ...

  7. awk sub string

    cat TFY1C.txt|awk '{print $0"\t"substr($4,1,4)}'> TFY1CRID.tx 1--从那位开始 4--多长

  8. python求列表中n个最大或最小的值

    import heapq #y为结果列表,n为所求的n个值,x为来源列表 y=heapq.nsmallest(n,x) y=heapq.nlargest(n,x)

  9. MySql 入门——日期计算

    MySQL自带的日期函数TIMESTAMPDIFF计算两个日期相差的秒数.分钟数.小时数.天数.周数.季度数.月数.年数,当前日期增加或者减少一天.一周等等 SELECT TIMESTAMPDIFF( ...

  10. 错误:为仓库 'appstream' 下载元数据失败 : Cannot prepare internal mirrorlist: No URLs in mirrorlist

    sudo sed -i -e "s|mirrorlist=|#mirrorlist=|g" /etc/yum.repos.d/CentOS-* sudo sed -i -e &qu ...