vue3 Pinia

vue3 pinia

学习记录来自 作者: 小满zs
学习地址


1. 简介pinia

Home | Pinia 中文文档 (web3doc.top)

pinia的特点:

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

(1)安装

yarn add pinia -S

npm install pinia -S

(2)引入注册Vue3

main.ts

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,
})

2. 初始化Store

  • 在src文件下创建文件夹(store)
  • 在store文件夹下创建 [name].ts
  • 创建一个store-namespace.ts存放唯一名称
export const enum Names {
    Test = 'TEST'
}
  • 引入store
import { defineStore } from 'pinia'
import { Names } from './store-namespace'
 
export const useTestStore = defineStore(Names.Test, {
 
})
  • 定义相关值
import { defineStore } from 'pinia'
import { Names } from './store-namespace'
 
export const useTestStore = defineStore(Names.Test, {
     state:()=>{
         return {
             current:1,
             name:''
         }
     },
     //类似于computed 可以帮我们去修饰我们的值
     getters:{
 
     },
     //可以操作异步 和 同步提交state
     actions:{
 
     }
})
  • 组件中使用
<template>current=>{{ current }}</template>

<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();
const current = ref(testStore.current);
</script>

<style scoped></style>

3. 操作state

(1)直接修改

<template>
  <button @click="change">change</button>
  current=>{{ testStore.current }}
</template>

<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();

const change = () => {
  testStore.current++;
};
</script>

<style scoped></style>

(2)批量修改 patch

<template>
  <button @click="change">change</button>
  <div>current=>{{ testStore.current }} name=>{{ testStore.name }}</div>
</template>

<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();

const change = () => {
  testStore.$patch({
    current: 10,
    name: "change",
  });
};
</script>

<style scoped></style>

函数带有state参数的形式,灵活性更高

<template>
  <button @click="change">change</button>
  <div>current=>{{ testStore.current }} name=>{{ testStore.name }}</div>
</template>

<script setup lang="ts">
import { useTestStore } from "./store/index";
const testStore = useTestStore();

const change = () => {
  testStore.$patch((state) => {
    state.current++;
    state.name += "X";
  });
};
</script>

<style scoped></style>

(3)通过原始对象修改整个实例

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

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

<template>
<button @click="change">change</button>
<div>current=>{{ testStore.current }} name=>{{ testStore.name }}</div>
</template>

<script setup lang="ts">
    import { useTestStore } from "./store/index";
    const testStore = useTestStore();

    const change = () => {
        testStore.$state = {
            current: 1,
            name: "12",
        };
    };
</script>

<style scoped></style>

(4)通过actions修改

import { defineStore } from 'pinia'
import { Names } from './store-namespace'

export const useTestStore = defineStore(Names.Test, {
    state: () => {
        return {
            current: 1,
            name: ""
        }
    },
    //类似于computed 可以帮我们去修饰我们的值
    getters: {

    },
    //可以操作异步 和 同步提交state
    actions: {
        // 设置name
        setName(name: string) {
            this.name = name
        }
    }
})
<template>
<button @click="change">change</button>
<div>current=>{{ testStore.current }} name=>{{ testStore.name }}</div>
</template>

<script setup lang="ts">
    import { useTestStore } from "./store/index";
    const testStore = useTestStore();
    // 使用
    const change = () => {
        testStore.setName("OKOK");
    };
</script>

<style scoped></style>

4. 解构store

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

<script setup lang='ts'>
    import { useTestStore } from './store'
    // 解决响应性丢失问题
    import { storeToRefs } from 'pinia'

    const Test = useTestStore()

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

    // const { current, name } = Test
    // 解构state信息 
    const { current, name } = storeToRefs(Test)

    console.log(current, name);

</script>

<style>
</style>

5. Actions

(1)同步调用

import { defineStore } from 'pinia'
import { Names } from './store-namespace'
export const useTestStore = defineStore(Names.TEST, {
    state: () => ({
        counter: 0,
    }),
    actions: {
        increment() {
            this.counter++
        },
        randomizeCounter() {
            this.counter = Math.round(100 * Math.random())
        },
    },
})
<template>
     <div>
         <button @click="Add">+</button>
          <div>
             {{Test.counter}}
          </div>    
     </div>
</template>
 
<script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {
     Test.randomizeCounter()
}
 
</script>
 
<style>
 
</style>

(2)异步调用

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;
        }
    },
})
<template>
     <div>
         <button @click="Add">test</button>
          <div>
             {{Test.user}}
          </div>    
     </div>
</template>
 
<script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {
     Test.getLoginInfo()
}
 
</script>
 
<style>
 
</style>

(3)相互调用

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

6. getters

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

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

  • 普通函数形式
    getters:{
       newCurrent ():number {
           return ++this.current
       }
    },
  • getters 互相调用
    getters:{
       newCurrent ():number | string {
           return ++this.current + this.newName
       },
       newName ():string {
           return `$-${this.name}`
       }
    },

7. 常用API

(1)$reset

重置store到他的初始状态

state: () => ({
     user: <Result>{},
     name: "default",
     current:1
}),
const reset = () => {
     Test.$reset()
}

(2)$subscribe

类似于Vuex 的abscribe 只要有state 的变化就会走这个函数

Test.$subscribe((args,state)=>{
   console.log(args,state);
})

如果你的组件卸载之后还想继续调用请设置第二个参数

Test.$subscribe((args,state)=>{
   console.log(args,state);
   
},{
  detached:true
})

(3)$onAction

只要有actions被调用就会走这个函数

Test.$onAction((args)=>{
   console.log(args);
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值