Pinia

# Pinia

简介 | Pinia (opens new window)

对于状态管理

在vue中可以通过 export const state = reactive({}) 来共享一个全局状态,当然这对单页应用来说是可以的,但是如果是在服务端渲染,会出现一些二安全问题。Pinia能解决这个问题

# 安装

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

# 基础使用

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  // 属性
    state: () => {
    return { count: 0 }
  },
  // 也可以这样定义
  // state: () => ({ count: 0 })
  
  // 方法
  actions: {
    increment() {
      this.count++
    },
  },
})

在一个组件中使用

<script setup>
import { useCounterStore } from '@/stores/counter'

const counter = useCounterStore()

counter.count++
// 自动补全! ✨
counter.$patch({ count: counter.count + 1 })
// 或使用 action 代替
counter.increment()
</script>

<template>
  <!-- 直接从 store 中访问 state -->
  <div>Current Count: {{ counter.count }}</div>
</template>

# 高级用法(常用的)

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('coubter',()=>{
    const count = ref(0)
    function increment(){
        count.value++
    }
    
    return { count , increment}
})

# 我在日常的工作项目中的一些写法:

用于的是数据一开始get的时候的状态管理,管理的展示部分的也就是get的数据

import {   ICommunityGroup, communityGroupApi } from '@/api/modules/setting' 
import { defineStore, storeToRefs } from 'pinia'
import { ref } from 'vue'

export const communityGroupStore = defineStore('communityGroupStore', () => {
  const communityGroupData = ref<ICommunityGroup[]>()
  const communityGroupPatams = ref({
      index: 1,
      title: '',
      group_ids: [] as string[],
  })

  const refetchCommunityGroup = ref(async () => {
    try {
      const { data } = await communityGroupApi.getComGroup(communityGroupPatams.value)
      if (data) {
        communityGroupData.value = data
      }
    } catch (error) {}
  })

  return { communityGroupData, refetchCommunityGroup }
})

export const useCommunityGroupStore = () => storeToRefs(communityGroupStore())

组件使用

<script>
import { useCommunityGroupStore } from '@/store/modules/setting'

const { communityGroupData, refetchCommunityGroup } = useCommunityGroupStore()

onMounted(async () => {
  // 注意返回的ref类型的所以要加.value
  communityGroupPatams.value = {
  	  index: 1,
      title: '123',
      group_ids: [] as string[],
  }// 修改参数
  await refetchCommunityGroup.value() // 根据参数调用get接口
  console.log(communityGroupData.value) // 打印值,一般这个值就是展示的数据了
})
</script>

# Vuex

Vuex 是什么? | Vuex (opens new window)

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库

# npm 或Yarn安装

npm install vuex@next --save
yarn add vuex@next --save

# 配置

新建store文件->index.js,进行如下配置,在main.js中进行引入

import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex)
 
export default new Vuex.Store({
  //数据,相当于data
  state: {
    
  },
  getters: {
    
  },
  //里面定义方法,操作state方发
  mutations: {
    
  },
  // 操作异步操作mutation
  actions: {
    
  },
  modules: {
    
  },
})

mian.js中

import vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
    router,
    store,
    render: h = > h(App)
}).$mount('#app')

vuex中一共有五个状态 State Getter Mutation Action Module

在Vuex中,我们需要先定义store,然后在组件中通过mapState、mapGetters、mapActions、mapMutations等方式来访问store。

// store.js
import Vuex from 'vuex'

export default new Vuex.Store({
  state: {
    count: 0,
  },
  mutations: {
    increment(state) {
      state.count++
    },
    decrement(state) {
      state.count--
    },
  },
  actions: {
    increment({ commit }) {
      commit('increment')
    },
    decrement({ commit }) {
      commit('decrement')
    },
  },
})


// 组件中使用
import { mapState, mapActions } from 'vuex'

export default {
  computed: mapState({
    count: state => state.count,
  }),
  methods: mapActions(['increment', 'decrement']),
}

# Pinia和vuex在使用上有什么区别

# 架构与使用的关键差异

# 状态定义与修改

Vuex要求通过严格的mutation来修改状态,这意味着每一个状态变更都需要经过预定义的mutation函数:

// Vuex典型状态管理
const store = new Vuex.Store({
  state: {
    count: 0,
    userInfo: null
  },
  mutations: {
    INCREMENT(state) {
      state.count++
    },
    SET_USER_INFO(state, userInfo) {
      state.userInfo = userInfo
    }
  },
  actions: {
    asyncIncrement({ commit }) {
      setTimeout(() => {
        commit('INCREMENT')
      }, 1000)
    }
  }
})

相比之下,Pinia允许直接修改状态,代码更加简洁自然:

// Pinia的状态管理
const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    userInfo: null
  }),
  actions: {
    increment() {
      this.count++ // 直接修改,无需commit
    },
    async fetchUserInfo() {
      // 支持异步操作
      const response = await fetchUser()
      this.userInfo = response.data
    }
  }
})

# 响应式与类型支持

Pinia原生支持TypeScript,提供更好的类型推导。状态默认是响应式的,组件可以直接使用store中的状态,无需额外的响应式转换。

# 模块化与代码组织

Vuex通过modules实现模块化,需要手动处理命名空间:

const moduleA = {
  namespaced: true,
  state: { ... },
  mutations: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA
  }
})

Pinia的模块化更加直观,可以轻松地创建和组合多个store:

const useUserStore = defineStore('user', { ... })
const useProductStore = defineStore('product', { ... })

# 性能与生态

  • Pinia更轻量(约1.6kb)
  • 运行时开销更低
  • 支持Tree-Shaking

Pinia的出现不仅仅是一个技术迭代,更体现了Vue生态对开发体验的持续追求 —— 让状态管理变得更加直观、高效和易用。它代表了前端状态管理的一个重要发展方向。