Pinia快速实践🐶

131 阅读2分钟

本文github地址:JavaScript_Everything 大前端知识体系与面试宝典,从前端到后端,全栈工程师,成为六边形战士


Pinia 与 Vuex 的区别

  1. 提供了 Compistion API
  2. Pinia与 TS 一起使用时具有可靠的类型推断支持
  3. 支持多 store,彼此相互独立,通过扁平化方式相互使用
  4. Pinia简化了流程,移除了mutation
  5. 去除了modules的嵌套结构

快速上手

初始化pinia

import {createPinia} from 'pinia'

const pinia = createPinia()

export default pinia

注册pinia

import { createApp } from 'vue'
import pinia from '../pinia/src/store'
import App from '../pinia/src/Views/App.vue'

const app = createApp(App)
app.use(pinia)
app.mount('#app')

给每一个store单独放一个文件

counter.js

import {defineStore} from 'pinia'

const useCounter = defineStore('counter', {
    state:()=>({
        counter: 1,
    }),
})

export default useCounter

组件中使用pinia定义的状态

<template>
  <div class="app">
    <h1>{{ counterStore.counter }}</h1>
  </div>
</template>

<script setup>
import useCounter from '../store/counter'
const counterStore = useCounter()
</script>

状态解构

解构会让状态失去响应式,因此不要在模板中使用解构后的数据。

如果要使用解构,需要手动将数据变为响应式

<template>
  <div class="app">
    <h1>{{ counter }}</h1>
    <button @click="increment">增加</button>
  </div>
</template>

<script setup>
import useCounter from '../store/counter'
import { storeToRefs } from 'pinia';
const counterStore = useCounter()
// 手动将数据变为响应式
const {counter} = storeToRefs(counterStore)
function increment(){
    counterStore.counter++
}
</script>

操作state

读写state

没有像vuex中复杂的流程,可以通过store实例直接修改状态

import useCounter from '../store/counter'
import { storeToRefs } from 'pinia';
const counteStore = counteStore()
function increment(){
    counteStore.counter++
}

重置状态

$reset方法可以将状态恢复到原始状态,在pinia内部缓存了初始值

function reset(){
    counterStore.$reset()
}

批量修改state

import useCounter from '../store/counter'
import { storeToRefs } from 'pinia';

const counterStore = useCounter()

function changeState(){
    counterStore.$patch({
        counter:100,
    })
}

整体替换state

const counteStore = useCounter()
counteStore.$state = {
    name : 'flten'
}

getters

getters扮演的作用相当于computed计算函数,对状态进行计算逻辑处理

getter中使用this访问到整个store的实例

基本使用

getter中访问状态可以使用state或者this(指向store实例)

定义getter

import {defineStore} from 'pinia'

const useCounter = defineStore('counter', {
    state:()=>({
        counter: 1,
    }),
    getters:{
        doubleCounter(state){
            return state.counter * 2
            // return this.counter * 2
        }
    }
})

使用getter

<h1>{{ counteStore.doubleCounter }}</h1>

getter中使用其他getter

    getters:{
        doubleCounter(state){
            return state.counter * 2
        },
        doubleCounterPlus(state, payload){
            // this指向store实例
            return function(payload){
                return this.doubleCounter + payload
            }
        }
    }

组件中使用:

<h1>{{ counteStore.doubleCounterPlus(10) }}</h1>

getter 中使用其他store中的状态数据

user.js定义的store

import {defineStore} from 'pinia'

const userUse = defineStore('user', {
    state:()=>({
        user: {
            name:'fltenwall'
        },
    }),
})

export default userUse

counter.js中使用user的状态数据:

import {defineStore} from 'pinia'
import userUse  from '../store/user';

const userCounter = defineStore('counter', {
    state:()=>({
        counter: 1,
    }),
    getters:{
        showUserInfo(state){
            const useUserInfo = userUse()
            return `${useUserInfo.user.name}'s counter is ${state.counter}`
        }
    }
})

组件中即可直接使用

<h1>{{ counterStore.showUserInfo }}</h1>

action

用途:将网络请求相关的业务逻辑放在actions

action中可以使用this访问到整个store的实例

同样去除了vuex中的繁琐流程,可以直接在组件中调用

简单用node写一个服务端并返回数据:

const http = require('http');

http.createServer((req, res)=>{
    // 处理跨域
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.writeHead(200);
    const data = [
        {id:111,name:'fltenwall'},
        {id:222,name:'fltenwall'}
    ]
    res.end(JSON.stringify(data));
}).listen(3000)

actions中处理网络请求逻辑:

import {defineStore} from 'pinia'
import userUse  from '../store/user';

const userCounter = defineStore('counter', {
    state:()=>({
        userList:[],
    }),
    actions:{
        async fetchUserData(){
            const res = await fetch('http://127.0.0.1:3000/')
            const data = await res.json(res)
            this.userList = data
        }
    }
})

export default userCounter

在组件中调用action发起网络数据:

<template>
  <div class="app">
    <ul>
        <li v-for="user in counterStore.userList">{{ user.name }}</li>
    </ul>
  </div>
</template>

<script setup>
import useCounter from '../store/counter'

const counterStore = useCounter()
// 获取服务端数据
counterStore.fetchUserData().then(res => {
    console.log('数据已获取')
})
</script>

本文github地址:JavaScript_Everything 大前端知识体系与面试宝典,从前端到后端,全栈工程师,成为六边形战士