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)

相关推荐
小小竹子4 分钟前
前端vue-实现富文本组件
前端·vue.js·富文本
万物得其道者成12 分钟前
React Zustand状态管理库的使用
开发语言·javascript·ecmascript
小白小白从不日白13 分钟前
react hooks--useReducer
前端·javascript·react.js
下雪天的夏风25 分钟前
TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错
前端·javascript·typescript
青稞儿31 分钟前
面试题高频之token无感刷新(vue3+node.js)
vue.js·node.js
diygwcom37 分钟前
electron-updater实现electron全量版本更新
前端·javascript·electron
volodyan40 分钟前
electron react离线使用monaco-editor
javascript·react.js·electron
^^为欢几何^^1 小时前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
Hello-Mr.Wang1 小时前
vue3中开发引导页的方法
开发语言·前端·javascript
程序员凡尘1 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js