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 分钟前
React Hooks
前端·javascript·react.js
迷途小码农零零发14 分钟前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀36 分钟前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪1 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef3 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6413 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻3 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云3 小时前
npm淘宝镜像
前端·npm·node.js
dz88i83 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr4 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook