Vuex和Pinia

Vuex概述

vuex是一个vue的状态管理工具,状态就是数据(多组件共享数据)。

优势:

  • 共同维护一份数据,数据集中化管理
  • 响应式变化
  • 操作简洁(vuex提供了一些辅助函数)

vuex的使用

安装vuex插件

复制代码
yarn add vuex@3

创建vuex模块文件

新建store/index.js专门存放vuex

创建仓库

复制代码
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store()

export default store

main.js导入挂载

html 复制代码
import Vue from 'vue'
import App from './App.vue'
import store from '@/store/index'

Vue.config.productionTip = false

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

state状态

1.提供数据

state提供唯一的公共数据源,所有共享的数据都要统一放到Store中的stare中储存。

在state对象中可以添加我们要共享的数据。

html 复制代码
const store = new Vuex.Store({
  state: {
    title: '大标题',
    count: 100
  }
})

2.使用数据

  1. 通过store直接访问
  2. 通过辅助函数(简化)

获取store:

  1. this.$store
  2. import 导入 stroe

直接访问

html 复制代码
<template>
  <div>
    <p>数据:{{ $store.state.count }}</p>
   <Son1Component></Son1Component>
  <Son2Component></Son2Component>
  </div>
</template>

辅助函数mapstate

mapstate是辅助函数,帮助我们把store中的数据自动映射到组件的计算机属性中。

导入mapState

html 复制代码
import { mapState } from 'vuex'

通过对象的方式映射

html 复制代码
  computed: {
    ...mapState(['count', 'title'])
  }

在模板中使用

html 复制代码
<template>
  <div>
    <p>数据:{{ count }}</p>
   <Son1Component></Son1Component>
  <Son2Component></Son2Component>
  </div>
</template>

mutations

1.定义mutations对象,对象中存放修改state的方法

html 复制代码
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    title: '大标题',
    count: 100
  },
  mutations: {
    addcount (state) {
      state.count += 1
    },
    subcount (state) {
      state.count -= 1
    }
  }
})

export default store

2.组件中提交调用mutations

html 复制代码
<template>
  <div>
    <p>数据:{{ this.$store.state.count }}</p>
<button @click="handleAdd">+1</button>
  </div>
</template>

<script>
export default {
  name: 'Son1Component',
  methods: {
    handleAdd () {
      this.$store.commit('addcount')
    }
  }
}
</script>

mutations传参语法

提交mutations是可以传递参数的'this.$store,commit('xxx',参数)'

1.提供mutation函数(带参数---提交载荷payload)

html 复制代码
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    title: '大标题',
    count: 100
  },
  mutations: {
    addcount (state, n) {
      state.count += n
    },
    subcount (state, n) {
      state.count -= n
    }
  }
})

export default store
html 复制代码
<template>
  <div>
    <p>数据:{{ this.$store.state.count }}</p>
<button @click="handleAdd(1)">+1</button>
<button @click="handleAdd(5)">+5</button>
  </div>
</template>

<script>
export default {
  name: 'Son1Component',
  methods: {
    handleAdd (n) {
      this.$store.commit('addcount', n)
    }
  }
}
</script>

传递多个参数时,可以包装成一个对象传递

html 复制代码
handleAdd (n) {
      this.$store.commit('addcount', {
        count: n,
        msg: 'haha'
      })
    }
html 复制代码
    addcount (state, obj) {
      state.count += obj.count
      console.log(obj.msg)
    }

input的实时输入更新

输入框渲染

html 复制代码
<input :value="count" @input="handInput" type="text" >

监听输入获取内容

html 复制代码
  methods: {
    handInput (e) {
      this.$store.commit('changecount', e.target.value)
    }

封装mutation处理函数

html 复制代码
  changecount (state, newcount) {
      state.count = newcount
    }

辅助函数mapMutations

mapMutations和mapState很像,它是把位于mutations中的方法提取了出来,映射到组件methods中

html 复制代码
<template>
  <div>
    <p>数据:{{ this.$store.state.count }}</p>
    <button @click="subcount(1)">-1</button>
  </div>
</template>

<script>
import { mapMutations } from 'vuex'
export default {
  name: 'Son1Component',
  methods: {
    ...mapMutations(['subcount'])
  }
}
</script>

actions

处理异步处理,mutations必须是同步的(便于监测数据变化,记录调试)

1.提供action方法

html 复制代码
  actions: {
    changecountactions (context, num) {
      setTimeout(() => {
        context.commit('changecount', num)
      }, 1000)
    }
  }

在页面中dispath调用

html 复制代码
    handchange (n) {
      this.$store.dispatch('changecountactions', n)
    }

辅助函数mapActions

mapActions是把位于actions中的方法提供了出来,映射到组件methods中

html 复制代码
<template>
  <div>
    <p>数据:{{ this.$store.state.count }}</p>
    <button @click="subcount(1)">-1</button>
    <button @click="changecountactions(888)">一秒改成888</button>
  </div>
</template>

<script>
import { mapMutations, mapActions } from 'vuex'
export default {
  name: 'Son1Component',
  methods: {
    ...mapMutations(['subcount']),
    ...mapActions(['changecountactions'])
  }
}
</script>

getters

类似于计算属性

除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters。

定义getters

  1. getters函数的第一个参数是state
  2. getters函数必须要有返回值
html 复制代码
  getters: {
    filterList (state) {
      return state.list.filter(item => item > 5)
    }
  }

访问getters

  1. 通过store访问getters
  2. 通过辅助函数mapGetters映射
html 复制代码
<div>{{ $store.getters.filterList }}</div>
html 复制代码
<template>
  <div>
    <p>数据:{{ this.$store.state.count }}</p>
    <button @click="subcount(1)">-1</button>
    <button @click="changecountactions(888)">一秒改成888</button>
    <hr>
    <div>{{ filterList }}</div>
  </div>
</template>

<script>
import { mapMutations, mapActions, mapGetters } from 'vuex'
export default {
  name: 'Son1Component',
  methods: {
    ...mapMutations(['subcount']),
    ...mapActions(['changecountactions'])
  },
  computed: {
    ...mapGetters(['filterList'])
  }
}
</script>

Pinia

Pinia是vue的专属的最新状态管理库,是Vuex状态管理工具的代替品

优点:

  1. 提供更简单的API(去掉了mutation)
  2. 提供符合,组合式风格的API(和Vue3新语法统一)
  3. 去掉了modules的概念,每一个store都是一个对立的模块
  4. 配合TypeScript更加友好,提供可靠的类型推断

手动添加Pinia到Vue项目

在实际开发项目时,关于Pinia的配置,可以在创建项目时自动添加

1.使用Vite创建一个空的Vue3项目

2.按照官方文档安装pinia项目中

html 复制代码
yarn add pinia
# 或者使用 npm
npm install pinia
javascript 复制代码
import './assets/main.css'

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

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

Pinia基础使用

1.定义store

javascript 复制代码
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const usecounterstore = defineStore('counter',()=>{
    const count = ref(100)
    return {
        count
    }
})

2.组件使用store

javascript 复制代码
<script setup>
import son1 from "@/components/son1.vue"
import son2 from "@/components/son2.vue"
import {usecounterstore} from "@/store/counter"
const counterstore = usecounterstore()
</script>

<template>
<div>
  <h3>数据:{{ counterstore.count }}</h3>
  <son1></son1>
  <son2></son2>
</div>
</template>
javascript 复制代码
import { defineStore } from 'pinia'
import { ref,computed } from 'vue'

export const usecounterstore = defineStore('counter',()=>{
    // 声明数据state
    const count = ref(100)
    // 声明操作数据的方法active(普通函数)

    const addcount = ()=>count.value++
    const subcount = ()=>count.value--
    
    //声明基于数据派生的计算属性getters(computed) 
    const double = computed(() => count.value*2)
    return {
        count,
        addcount,
        subcount,
        double
    }
})

active异步实现

javascript 复制代码
import { defineStore } from 'pinia'
import { ref,computed } from 'vue'

export const usecounterstore = defineStore('counter',()=>{
    // 声明数据state
    const count = ref(100)
    // 声明操作数据的方法active(普通函数)

    const addcount = ()=>count.value++
    const subcount = ()=>count.value--
    
    //声明基于数据派生的计算属性getters(computed) 
    const double = computed(() => count.value*2)
    return {
        count,
        addcount,
        subcount,
        double
    }
})
javascript 复制代码
<script setup>
import son1 from "@/components/son1.vue"
import son2 from "@/components/son2.vue"
import {usecounterstore} from "@/store/counter"
import {usechannelstore} from "@/store/channel"
const counterstore = usecounterstore()
const usestore = usechannelstore()
</script>

<template>
<div>
  <h3>数据:{{ counterstore.count }}</h3>
  <son1></son1>
  <son2></son2>
  <hr>
  <button @click="usestore.getlist">获取数据</button>
  <ul>
    <li v-for="item in usestore.channellist" :key="item.id">{{ item.name }}</li>
  </ul>
</div>
</template>

storeToRefs

用于将 Pinia store 实例中的状态属性转换为 ref 对象。

javascript 复制代码
import { defineStore } from 'pinia';

const useMyStore = defineStore({
  id: 'myStore',
  state: () => ({
    count: 0,
    text: 'Hello, Pinia!',
  }),
});

// 在组件中使用 storeToRefs 将状态转换为 ref 对象
const myStore = useMyStore();
const { count, text } = pinia.storeToRefs(myStore);

Pinia持久化

1.安装插件 pinia-plugin-persistedstate

javascript 复制代码
npm i pinia-plugin-persistedstate

2.main.js使用

import persist from 'pinia-plugin-persistedstate'

...

app.use(createPinia().use(persist))

javascript 复制代码
import './assets/main.css'

import persist from 'pinia-plugin-persistedstate'
import { createApp } from 'vue'
import {createPinia} from 'pinia'
import App from './App.vue'

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

3.store仓库中,persist:true开启

javascript 复制代码
import { defineStore } from 'pinia'
import { ref,computed } from 'vue'

export const usecounterstore = defineStore('counter',()=>{
    // 声明数据state
    const count = ref(100)
    // 声明操作数据的方法active(普通函数)

    const addcount = ()=>count.value++
    const subcount = ()=>count.value--
    
    //声明基于数据派生的计算属性getters(computed) 
    const double = computed(() => count.value*2)
    return {
        count,
        addcount,
        subcount,
        double
    }
},{
    persist:true
})

详细见配置 | pinia-plugin-persistedstate (prazdevs.github.io)

相关推荐
崔庆才丨静觅11 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606112 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了12 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅12 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅12 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅13 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment13 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅13 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊13 小时前
jwt介绍
前端
爱敲代码的小鱼13 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax