Vue3 new generation state manager - learning and use of pinia

One, vuex and pinia

insert image description here

Pinia started out as an exploration of what the next iteration of Vuex might look like, incorporating many ideas from the Vuex 5 core team discussions. Eventually, we realized that Pinia had implemented most of what we wanted in Vuex 5, and decided to implement it instead with new suggestions.

It can be understood that pinia is the next generation of vuex5, but the vuex team directly uses pinia to name it in order to respect the pinia author's contribution to the development of vuex.
Pinia Chinese Documentation

characteristic

  1. Full support for typescript
  2. Lightweight enough, the compressed volume is only 1.6kb
  3. Modular design, each store introduced during packaging can be automatically split
  4. There is no nesting of modules, only the concept of store, and stores can be used freely to achieve better code separation
  5. Actions support synchronous and asynchronous, without mutation
  6. Support for VueDevtools

2. Use pinia

2.1 install pinia

Install pinia with your favorite package manager:

yarn add pinia
# 或者使用 npm
npm install pinia

2.2 Project introduction

Use createPinia to introduce pinia into your project.

main.ts:

import {
    
     createPinia } from 'pinia'
import {
    
     createApp } from 'vue'
import App from './App.vue'

createApp(App).use(createPinia()).mount('#app')

2.3 create store

Create a store folder under the src directory to store the js/ts files corresponding to the store. It will be convenient for management in the future. We can define only one store in a js/ts file. For example, we define a user.ts file to store users Related information and operations:
insert image description here
pinia uses defineStore to create a store, including id, state, getters and actions:

// @ts-check
import {
    
     defineStore } from 'pinia'

/**
 * Simulate a login
 */
function apiLogin(a: string, p: string) {
    
    
  if (a === 'ed' && p === 'ed') return Promise.resolve({
    
     isAdmin: true })
  if (p === 'ed') return Promise.resolve({
    
     isAdmin: false })
  return Promise.reject(new Error('invalid credentials'))
}

export const useUserStore = defineStore({
    
    
  id: 'user',
  state: () => ({
    
    
    name: 'Eduardo',
    isAdmin: true,
  }),
  
  getters:{
    
    
	userName: (state) => `Get userName from getter ${
      
      state.name}`
  },
  
  actions: {
    
    
  /**
  * 退出logout
  */
    logout() {
    
    
      this.$patch({
    
    
        name: '',
        isAdmin: false,
      })
  /**
   * 登录 login
   */
    async login(user: string, password: string) {
    
    
      const userData = await apiLogin(user, password)
      this.$patch({
    
    
        name: user,
        ...userData,
      })
    },
  },
})

Compared with vuex, pinia removes mutation, both synchronous and asynchronous operations pass actions, and there is no concept of module, defineStore will create a new store.

2.4 Using stores

Introduce the defined store in the component and call:

<script setup lang="ts">
import {
      
       useUserStore } from "./store/user"

const userStore = useUserStore()

//访问state
console.log(userStore.name)
//访问getter
console.log(userStore.userName)
</script>

Then you can access the state in the store through the user, and you can also call the getter and action.

getter

Getter is exactly equivalent to Store state 计算值. They can be defined with the getters property in defineStore(). They receive "state" as the first argument to encourage the use of arrow functions, which can access getters directly on the store instance.
We can also access the entire store instance through this when defining regular functions.

action

Actions are equivalent to methods in components. They can be defined using the actions attribute in defineStore(), and they are great for defining business logic, as well as calling actions directly on the store instance.
In actions, you can also access the entire store instance through this when defining regular functions.

export const useStore = defineStore('main', {
    
    
  state: () => ({
    
    
    counter: 0,
  }),
  actions: {
    
    
    increment() {
    
    
      this.counter++
    },
    randomizeCounter() {
    
    
      this.counter = Math.round(100 * Math.random())
    },
  },
})

2.5 modify state

1. Direct modification

Although it can be modified directly through the pinia instance, for the sake of code structure, the global state management should not directly modify the state at each component, it should be modified in a unified way in the action (piain has no mutation) is not recommended!

store.count ++;

2. Use $patch

Using $patch to change data $patch can modify multiple values ​​at the same time.

store.$patch((state) => {
    
    
        state.name= 'newName'
        state.age ++
      })

3. Use actions

recommend.

actions:{
    
    
    async login(user: string, password: string) {
    
    
      //模拟异步登录
      const userData = await apiLogin(user, password)
      //更新state中数据
      this.$patch({
    
    
        name: user,
        ...userData,
      })
    }
}

2.6 storeToRefs

In order to directly obtain the attributes in the store, we may use destructuring to obtain directly:

import {
    
     useUserStore } from "./store/user"

const {
    
     name }= useUserStore()

However, it is worth noting that if you directly deconstruct the store instance to obtain the value in the state, the obtained value will lose its responsiveness. The correct way is to use storeToRefs:

import {
    
     storeToRefs } from 'pinia'
import {
    
     useUserStore } from "./store/user"

const {
    
     name }= storeToRefs(useUserStore())

Guess you like

Origin blog.csdn.net/ZHANGYANG_1109/article/details/128036448