# 状态管理 Pinia

# 介绍

uni-app 内置了 Pinia (opens new window)

使用 HBuilder X 不需要手动安装,直接使用即可。使用 CLI 需要手动安装,执行 yarn add pinianpm install pinia

# Pinia 是什么?

Pinia(发音为 /piːnjʌ/,如英语中的 peenya) 是 Vue 的存储库,它允许您跨组件、页面共享状态。在服务器端以及小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:

  • 开发工具支持
    • 跟踪动作、突变的时间表
    • 存储出现在使用它们的组件中
    • 时间旅行和更容易的调试
  • 热模块更换
    • 修改您的存储而不重载您的页面
    • 在开发过程中保持任何现有状态
  • 为 JS 用户提供适当的 TypeScript 支持或自动完成功能

# 项目结构

├── pages
├── static
└── stores
    └── counter.js
├── App.vue
├── main.js
├── manifest.json
├── pages.json
└── uni.scss

# 基本示例

main.js 中编写以下代码:

import { createSSRApp } from 'vue';
import * as Pinia from 'pinia';

export function createApp() {
	const app = createSSRApp(App);
	app.use(Pinia.createPinia());
	return {
		app,
		Pinia, // 此处必须将 Pinia 返回
	};
}

首先创建一个商店:

// stores/counter.js
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
	state: () => {
		return { count: 0 };
	},
	// 也可以这样定义
	// state: () => ({ count: 0 })
	actions: {
		increment() {
			this.count++;
		},
	},
});

然后在组件中使用它:

import { useCounterStore } from '@/stores/counter';

export default {
	setup() {
		const counter = useCounterStore();

		counter.count++;
		// 可以手动触发
		counter.$patch({ count: counter.count + 1 });
		// 或者使用 actions
		counter.increment();
	},
};

你甚至可以使用一个函数(类似于一个组件 setup())来为更高级的用例定义一个 Store:

export const useCounterStore = defineStore('counter', () => {
	const count = ref(0);
	function increment() {
		count.value++;
	}

	return { count, increment };
});

如果您仍然不熟悉 setup() Composition API,请不要担心,Pinia 还支持一组类似 Vuex 的 map helpers

您以相同的方式定义存储,然后使用 mapStores()mapState()mapActions() 访问:

const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    }
  }
})

const useUserStore = defineStore('user', {
  // ...
})

export default {
  computed: {
    // 其他的计算属性
    // ...
    // 通过 this.counterStore 和 this.userStore 访问
    ...mapStores(useCounterStore, useUserStore)
    // 通过 this.count 和 this.double 访问
    ...mapState(useCounterStore, ['count', 'double']),
  },
  methods: {
    // 通过 this.increment() 访问
    ...mapActions(useCounterStore, ['increment']),
  },
}