目录

[TOC]

什么是pinia

官方文档:https://pinia.web3doc.top/

Pinia 是 Vue 的专属状态管理库,可以实现跨组件或页面共享状态,是 vuex 状态管理工具的替代品,和 Vuex相比,具备以下优势

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

安装

1
2
3
4
5
6
7
8
9
10
# 创建一个vue3项目 具体使用查看本站vue3文档
npm init vue@latest

# 安装 pinia
npm i pinia

# 打开main.js文件加入下面代码
import { createPinia } from 'pinia'

createApp(App).use(createPinia()).mount('#app')

使用

  • 创建store:在src目录下创建一个stores文件夹,里面定义一个一个的store(一个一个的js文件,比如 userInfo.js、category.js等)

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

    export const usePersonStore = defineStore('person', () => {
    // 定义属性
    const person = ref({
    username: "123456",
    password: "xiaofei"
    })

    // 定义方法
    const updateUsername = () => {
    person.value.username = "xiaofei"
    }
    const updatePassword = () => {
    person.value.password = "123456"
    }

    // 将定义的属性和方法返回
    return {
    person, updateUsername, updatePassword
    }
    })
  • 使用store

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <script setup>
    import {usePersonStore} from '@/stores/person'


    const storePerson = usePersonStore()
    //获取state里面的变量
    console.log(storePerson.person.username)
    console.log(storePerson.person.password)
    //获取actions里面的方法
    storePerson.updatePassword()
    </script>

    <template>
    <!-- 使用state里面定义的变量,获取用户名和密码 -->
    <div>{{ storePerson.person.username }}</div>
    <div>{{ storePerson.person.password }}</div>
    <!-- 使用actions里面定义的方法 -->
    <button @click="storePerson.updateUsername">修改用户名</button>
    </template>

getters

getters直接使用计算属性即可实现

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

export const usePersonStore = defineStore('person', () => {
// 定义属性
const person = ref({
username: "123456",
})

//使用计算属性定义getters
const updateUsernameGetters = computed(() => person.value.username + ":计算属性后的值")

// 定义方法
const updateUsername = () => {
person.value.username = "xiaofei"
}

// 将定义的属性和方法返回
return {
person, updateUsernameGetters, updateUsername
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script setup>
import {usePersonStore} from '@/stores/person'


const storePerson = usePersonStore()
//获取state里面的变量
console.log(storePerson.person.username)
</script>

<template>
<!-- 使用state里面定义的变量,获取用户名和密码 -->
<div>{{ storePerson.person.username }}</div>
<!-- 使用计算属性定义getters -->
<div>{{ storePerson.updateUsernameGetters}}</div>
<!-- 使用actions里面定义的方法 -->
<button @click="storePerson.updateUsername">修改用户名</button>
</template>

action

  • store中定义action
  • 组件中触发action
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import {defineStore} from 'pinia'
import {ref} from 'vue'
import axios from "axios";

export const usePersonStore = defineStore('person', () => {
// 定义属性
const dataList = ref([])

// 异步 action,async和await必须有
const loadList = async () => {
const res = await axios.get('http://geek.itheima.net/v1_0/channels')
dataList.value = res.data.data.channels
}

// 将定义的属性和方法返回
return {
dataList, loadList
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script setup>
import {usePersonStore} from '@/stores/person'

const storePerson = usePersonStore()

// 调用定义的actions方法
storePerson.loadList()
</script>

<template>
<ul>
<li v-for="item in storePerson.dataList" :key="item.id">{{ item.name }}</li>
</ul>
</template>

storeToRefs获取ref定义数据(推荐)

storeToRefs只能获取state和getters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import {defineStore} from 'pinia'
import {ref} from 'vue'
import axios from "axios";

export const usePersonStore = defineStore('person', () => {
// 定义属性
const dataList = ref([])

// 异步 action,async和await必须有
const loadList = async () => {
const res = await axios.get('http://geek.itheima.net/v1_0/channels')
dataList.value = res.data.data.channels
}

// 将定义的属性和方法返回
return {
dataList, loadList
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script setup>
import {usePersonStore} from '@/stores/person'
import {storeToRefs} from "pinia/dist/pinia";

const storePerson = usePersonStore()
//使用storeToRefs获取ref定义数据
const {dataList} = storeToRefs(storePerson)

//函数不能使用storeToRefs获取,只能使用获取的对象直接调用
storePerson.loadList()
</script>

<template>
<ul>
<li v-for="item in dataList" :key="item.id">{{ item.name }}</li>
</ul>
</template>

pinia持久化