1.1核心概念
vuex中有四个核心概念:
- State
- Getters
- Mutaions
- Actions
在Pinia中:
- State
- Getters
- Actions 同步异步都支持
1.2基本示例
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
// could also be defined as
// state: () => ({ count: 0 })
actions: {
increment() {
//在vuex中我们需要搞两步
//1.定义mutations
//2.提交mutations
this.count++
},
},
})
然后在组件中使用它:
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counter = useCounterStore()
counter.count++
// with autocompletion ✨
counter.$patch({ count: counter.count + 1 })
// or using an action instead
counter.increment()
},
}
1.3Pinia vs Vuex
2.快速入门
2.1安装
yarn add pinia
# or with npm
npm install pinia
2.2初始化配置
Vue3:
import { createPinia } from 'pinia'
app.use(createPinia())
Vue2:
如果您使用的是 Vue 2,您还需要安装一个插件并pinia在应用程序的根目录插入创建的插件:
import { createPinia, PiniaVuePlugin } from 'pinia'
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
new Vue({
el: '#app',
// other options...
// ...
// note the same `pinia` instance can be used across multiple Vue apps on
// the same page
pinia,
})
2.3用vite来创建一个项目
1.下载vite
npm init vite@latest
2.创建项目名
pinia-examples
3.选择vue
4.用ts还是不用
选择vue-ts
5.npm install pinia
6.打开main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia} from 'pinia'
//创建Pinia实例
const pinia=createPinia()
const app=createApp(App)
//挂载到Vue根实例
app.use(pinia)
app.mount('#app')
7.创建src\store\index.ts
文件
import { defineStore}from 'pinia'
// 1.定义并导出容器
//参数1:容器的ID,必须唯一,将来Pinia会把所有的容器挂载到根容器
//参数2:选项对象
//返回值:
export const useMainStore=defineStore('main',{
/*
类似于组件的data,用来存储全局状态的
1.必须是函数:这样是为了在服务端渲染的时候避免交叉请求导致的数据状态污染
2.必须是箭头函数,这是为了更好的TS类型推导
*/
state:()=>{
return {
count:100,
foo:'bar',
arr:[1,2,3]
}
},
// 类似于组件的computed,用来封装计算属性,有缓存的功能
//函数接受一个可选参数,state状态对象
getters:{
count10(state){
console.log('count10 调用了')
return state.count+10
}
//如果再getters中使用了this,则必须手动指定返回值的类型,否则类型推导不出来
// count10(): number{
// console.log('count10 调用了')
// return this.count+10
// }
},
// 类似于组件的methods,封装业务逻辑,修改state
actions:{
//注意:不能使用箭头函数定义,因为箭头函数绑定外部this
changeState(){
//优化前
// this.count++
// this.foo='hello'
// this.arr.push(4)
//优化后,批量更新
//如果涉及数据比较多,则推荐使用仓库实例的$patch方法,
//批量修改,虽然看起来和前面的几乎没有区别,但是会加快修改速度,
//对程序的性能有很大的好处。$patch传入一个对象,对象的属性就是各种状态
this.$patch(state=>{
state.count++
state.foo='hello'
state.arr.push(4)
})
}
}
})
8.修改HelloWorld.vue
<template>
<p>{{mainStore.count}}</p>
<p>{{mainStore.foo}}</p>
<p>{{mainStore.arr}}</p>
<p>{{mainStore.count10}}</p>
<p>{{mainStore.count10}}</p>
<p>{{mainStore.count10}}</p>
<hr>
<p>{{count}}</p>
<p>{{foo}}</p>
<hr>
<p>
<button @click="handleChangeState">修改数据</button>
</p>
</template>
<script lang="ts" setup>
import {storeToRefs} from 'pinia'
import {useMainStore} from '../store'
const mainStore=useMainStore()
console.log(mainStore.count)
//这是有问题的,因为这样拿到的数据不是响应式的,是一次性的
//Pinia 其实就是把state数据都做了reactive处理了
//const {count,foo}=mainStore
//解决办法就是使用
//把结构出来的数据做ref响应式代理
const {count,foo}=storeToRefs(mainStore)
const handleChangeState=()=>{
//方式一:
//mainStore.count++
//mainStore.foo='hello'
//方式二:如果需要修改多个数据,建议使用$patch批量更新
// mainStore.$patch({
// count:mainStore.count+1,
// foo:'hello',
// arr:[...mainStore.arr,4]
// })
//方式三:更好的批量更新的方式: $patch 一个函数
// mainStore.$patch(state=>{
// state.count++
// state.foo='hello'
// state.arr.push(4)
// })
//方式四:逻辑比较多的时候可以封装到actions做处理
mainStore.changeState()
}
</script>