Pinia 介绍

Pinia 起始于 2019 年 11 月左右的一次实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库。从那时起,我们就倾向于同时支持 Vue 2 和 Vue 3,并且不强制要求开发者使用组合式 API,我们的初心至今没有改变。除了安装和 SSR 两章之外,其余章节中提到的 API 均支持 Vue 2 和 Vue 3。虽然本文档主要是面向 Vue 3 的用户,但在必要时会标注出 Vue 2 的内容,因此 Vue 2 和 Vue 3 的用户都可以阅读本文档。

完整的 ts 的支持;

•足够轻量,压缩后的体积只有1kb左右;•去除 ,只有 state,,;• 支持同步和异步;•代码扁平化没有模块嵌套vue箭头函数,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的•无需手动添加 storevue箭头函数,store 一旦创建便会自动添加;•支持Vue3 和 Vue2

为什么要使用 Pinia:

Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态。

如果您熟悉 API,您可能会认为您已经可以通过一个简单的 const state = ({}). 这对于单页应用程序来说是正确的,但如果它是服务器端呈现的,会使您的应用程序暴露于安全漏洞。 但即使在小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:

dev-tools 支持 跟踪动作、突变的时间线 Store 出现在使用它们的组件中 time 和 更容易的调试 热模块更换 在不重新加载页面的情况下修改您的 Store 在开发时保持任何现有状态 插件:使用插件扩展 Pinia 功能 为 JS 用户提供适当的 支持或 服务器端渲染支持

官方文档Pinia[1]

git 地址[2]

Pinia 安装和引入起步 安装

yarn add pinia
npm install pinia

引入注册Vue3

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

Vue2 使用

import { createPinia, PiniaVuePlugin } from 'pinia'
Vue.use(PiniaVuePlugin)const pinia = createPinia()
new Vue({ el: '#app', // other options... // ... // note the same `pinia` instance can be used across multiple Vue apps on // the same page pinia,})

Pinia 初始化仓库Store

1.新建一个文件夹Store 2.新建文件[name].ts

3.定义仓库Store

import { defineStore } from 'pinia'

4.我们需要知道存储是使用定义的(),并且它需要一个唯一的名称,作为第一个参数传递

这儿名称抽离出去了, 新建文件store-/index.ts

export const enum Names {    Test = 'TEST'}

store 引入

import { defineStore } from 'pinia'import { Names } from './store-namespace'
export const useTestStore = defineStore(Names.Test, {
})

这个名称,也称为id,是必要的,Pania 使用它来将商店连接到 。将返回的函数命名为use...是可组合项之间的约定,以使其使用习惯。

•1.定义值

State 箭头函数 返回一个对象 在对象里面定义值

import { defineStore } from 'pinia'import { Names } from './store-namespce'
export const useTestStore = defineStore(Names.Test, { state:()=>{ return { current:1 } }})

import { defineStore } from 'pinia'import { Names } from './store-namespce'
export const useTestStore = defineStore(Names.Test, { state:()=>{ return { current:1 } }, //类似于computed 可以帮我们去修饰我们的值 getters:{
}, //可以操作异步 和 同步提交state actions:{
}})

修改 .State 是允许直接修改值的

例如++

     
<button @click="Add">+
{{Test.current}}

<script setup lang='ts'>import {useTestStore} from './store'const Test = useTestStore()const Add = () => { Test.current++ // 注意这里}

VUEX 不允许如此修改,必须通过提交,pinia可以直接修改

2.批量修改State的值 -- $patch

实例上有$patch方法可以批量修改多个值

     
<button @click="Add">+
{{Test.current}}
{{Test.age}}

<script setup lang='ts'>import {useTestStore} from './store'const Test = useTestStore() const Add = () => { Test.$patch({ // 注意这里 current:200, age:300 })}

3.批量修改函数形式

推荐使用函数形式 可以自定义修改逻辑

     
<button @click="Add">+
{{Test.current}}
{{Test.age}}

<script setup lang='ts'>import {useTestStore} from './store'const Test = useTestStore()const Add = () => { Test.$patch((state)=>{ // 注意这里 .$patch state.current++; state.age = 40 })}

4.通过原始对象修改整个实例

$state您可以通过将store的属性设置为新对象来替换store的整个状态

缺点就是必须修改整个对象的所有属性

     
<button @click="Add">+
{{Test.current}}
{{Test.age}}

<script setup lang='ts'>import {useTestStore} from './store'const Test = useTestStore()const Add = () => { Test.$state = { // 注意这里 .$state current:10, age:30 } }

5.通过修改

定义

在 中直接使用this就可以指到state里面的值

import { defineStore } from 'pinia'import { Names } from './store-naspace'export const useTestStore = defineStore(Names.TEST, {     state:()=>{         return {            current:1,            age:30         }     },
actions:{ // 注意这里 setCurrent setCurrent () { // 这里不要写箭头函数,否则this指向会错误 this.current++ } }})

使用方法直接在实例调用

     
<button @click="Add">+
{{Test.current}}
{{Test.age}}

<script setup lang='ts'>import {useTestStore} from './store'const Test = useTestStore()const Add = () => { Test.setCurrent() // 注意这里 setCurrent}

解构store

在Pinia是不允许直接解构,是会失去响应性的

const Test = useTestStore() 
const { current, name } = Test
console.log(current, name);

差异对比

修改Test 解构完之后的数据不会变

而源数据是会变的

  
origin value {{Test.current}}
pinia:{{ current }}--{{ name }} change : <button @click="change">change

<script setup lang='ts'>import { useTestStore } from './store' const Test = useTestStore()
const change = () => { Test.current++}
const { current, name } = Test console.log(current, name);

解决方案可以使用

import { storeToRefs } from 'pinia'
const Test = useTestStore()
const { current, name } = storeToRefs(Test) // storeToRefs

其原理跟 一样的给里面的数据包裹一层toref 源码 通过toRaw使store变回原始数据防止重复代理 循环store 通过 isRef 判断 如果是响应式对象直接拷贝一份给refs 对象 将其原始对象包裹toRef 使其变为响应式对象

vue箭头函数_箭头函数的this指向哪里_箭头函数有自己的this吗

,(支持同步异步)1.同步 直接调用即可

import { defineStore } from 'pinia'import { Names } from './store-naspace'export const useTestStore = defineStore(Names.TEST, {    state: () => ({        counter: 0,    }),    actions: {        increment() {            this.counter++        },        randomizeCounter() {            this.counter = Math.round(100 * Math.random())        },    },})

     
<button @click="Add">+
{{Test.counter}}

<script setup lang='ts'>import {useTestStore} from './store'const Test = useTestStore()const Add = () => { Test.randomizeCounter()}

2.异步 可以结合async await 修饰

import { defineStore } from 'pinia'import { Names } from './store-naspace'
type Result = { name: string isChu: boolean}
const Login = (): Promise<Result> => { return new Promise((resolve) => { setTimeout(() => { resolve({ name: '小', isChu: true }) }, 3000) })}
export const useTestStore = defineStore(Names.TEST, { state: () => ({ user: <Result>{}, name: "123" }), actions: { async getLoginInfo() { const result = await Login() this.user = result; } },})

     
<button @click="Add">test
{{Test.user}}

<script setup lang='ts'>import {useTestStore} from './store'const Test = useTestStore()const Add = () => { Test.getLoginInfo()}

3.多个互相调用

state: () => ({    user: <Result>{},    name: "default"}),actions: {    async getLoginInfo() {        const result = await Login()        this.user = result;        this.setName(result.name) // 这里    },    setName (name:string) {        this.name = name;    }},

.使用箭头函数不能使用this, this指向已经改变指向 修改值请用state

主要作用类似于 数据修饰并且有缓存

getters:{    newPrice:(state)=> `$${state.user.price}`},

2.普通函数形式可以使用this

getters:{    newCurrent ():number {        return ++this.current    }},

3. 互相调用

getters:{    newCurrent ():number | string {        return ++this.current + this.newName    },    newName ():string {        return `$-${this.name}`    }},

API1.$reset

重置store到他的初始状态

state: () => ({     user: <Result>{},     name: "default",     current:1}),

Vue 例如我把值改变到了10

const change = () => {     Test.current++}

调用$reset(); 将会把state所有值 重置回 原始状态

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注