pinia入门教程

安装

1
npm i pinia

定义 store

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/store/index.js
import { defineStore } from 'pinia'

export const mainStore = defineStore('main', {
state: () => {
return {
count: 0,
msg: 'hello world',
}
},
getters: {},
actions: {},
})

使用 pinia

1
2
3
4
// src/main.js
import { createPinia } from 'pinia'
const pinia = createPinia()
app.use(pinia)

在页面中使用 store

1
2
3
4
5
6
7
8
<template>
<div>{{store.count}}</div>
</template>

<script setup>
import { mainStore } from '../store/index'
const store = mainStore()
</script>

解构 Store

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div>{{store.count}}</div>
<br />
<h2>使用storeToRefs来解构store</h2>
<div>{{count}}</div>
</template>

<script setup>
import { mainStore } from '../store/index'
import { storeToRefs } from 'pinia'
const store = mainStore()
const { count } = storeToRefs(store)
</script>

修改 Pinia 数据状态

简单数据修改

简单数据直接通过在方法中操作store.属性名来修改

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div>{{store.count}}</div>
<button @click="handleClick">简单数据修改</button>
</template>

<script setup>
import { mainStore } from '../store/index'
const store = mainStore()

const handleClick = () => {
store.count++
}
</script>

多条数据修改

通过store.属性名的方式逐行修改是可以的,但是 pinia 官网推荐使用$patch来修改多条数据。

$patch接受两个类型的参数,分别为对象和函数

  1. $patch + 对象
  2. $patch + 函数:通过函数方式去使用的时候,函数接受一个 state 的参数,state 就是 store 仓库中的 state
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<div>{{store.count}}</div>
<div>{{store.msg}}</div>
<button @click="onObjUpdate">简单数据修改</button>
<button @click="onFuncUpdate">简单数据修改</button>
</template>

<script setup>
import { mainStore } from '../store/index'
const store = mainStore()

const onObjUpdate = () => {
store.$patch({
count: state.count + 2,
msg: state.msg === 'hello world' ? 'hello guozhaoxi' : 'hello world',
})
}

const onFuncUpdate = () => {
store.$patch((state) => {
;(state.count = state.count + 2),
(state.msg =
state.msg === 'hello world' ? 'hello guozhaoxi' : 'hello world')
})
}
</script>

通过 action 修改数据

在 store.actions 中添加一个changeState方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { defineStore } from 'pinia'

export const mainStore = defineStore('main', {
state: () => {
return {
msg: 'hello world',
count: 0,
}
},
getters: {},
actions: {
changeState() {
this.count++
this.msg = this.msg === 'hello world' ? 'hello guozhaoxi' : 'hello world'
},
},
})

在组件中使用store.方法名的方式调用该方法

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<button @click="handleClick">actions修改多个状态</button>
</template>

<script setup>
import { mainStore } from '../store/index'
const store = mainStore()

const handleClick = () => {
store.changeState()
}
</script>

Pinia 中的 getters

Pinia 中的 getter 和 Vue 中的计算属性几乎一样,在获取 State 值之前做一些逻辑处理。

  1. getter 中的值有缓存特性,如果值没有改变,多次使用也只会调用一次

添加 getter 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { defineStore } from 'pinia'

export const mainStore = defineStore('main', {
state: () => {
return {
msg: 'hello world',
count: 0,
}
},
getters: {
getCountBuff(state) {
console.log('getter被调用')
return `${state.count}***${state.count}`
},
},
actions: {
changeState() {
this.count++
},
},
})

组件内多次调用 getter

1
2
3
4
5
6
7
8
<template>
<h2>getter 获取数据</h2>
<p>{{ store.getCountBuff }}</p>
<p>{{ store.getCountBuff }}</p>
<p>{{ store.getCountBuff }}</p>
<p>{{ store.getCountBuff }}</p>
<p>{{ store.getCountBuff }}</p>
</template>

打开浏览器控制台我们发现,多次调用同一个 getter 函数的时候,只会执行一次,说明 getter 是具有缓存性的。

  1. getter 中不仅可以传递 state直接改变数据状态,还可以使用 this 来改变数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mport { defineStore } from 'pinia'

export const mainStore = defineStore('main', {
state: () => {
return {
msg: 'hello world',
count: 0,
}
},
getters: {
getMsgWithThis(state) {
return `${this.msg}***${this.msg}`
},
},
actions: {
changeState() {
this.count++
},
},
})

store 之间的相互调用

我们定义一个新的 store

1
2
3
4
5
6
7
8
9
10
11
import { defineStore } from 'pinia'

export const bookStore = defineStore('book', {
state: () => {
return {
books: ['语文', '数学', '英语'],
}
},
getters: {},
actions: {},
})

mainStore中引入使用我们上面刚刚定义好的bookStore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { defineStore } from 'pinia'
import { bookStore } from './book'

export const mainStore = defineStore('main', {
state: () => {
return {
msg: 'hello world 123',
count: 0,
}
},
getters: {
getCountBuff(state) {
console.log('getter被调用')
return `${state.count}***${state.count}`
},
getBooks() {
return bookStore().books
},
},
actions: {
changeState() {
this.count++
},
},
})

在组件中使用

1
2
3
4
5
6
7
8
9
<template>
<h2>获取另一个store中的数据</h2>
<p>{{ store.getBooks }}</p>
</template>

<script>
import { mainStore } from '../store/index'
const store = mainStore()
</script>