Vue3 has been around for a while now, with a new responsive system and a new Composition API built. The ecosystem around Vue is adapting to the new system. The official state management library Vuex is also adapting, and a new proposal for Vuex 5 has been put forward.

  • Two syntax are supported for creating stores:Options ApiComposition Api;
  • deletemutations, only supportstate,getters,actions;
  • Modular design, good support for code segmentation;
  • There are no nested modules, just the concept of Store;
  • The completeTypeScriptSupport;

There was an interesting comment under the proposal. A brief translation:

Unfortunately, the proposal of Vex5 has nothing to do with the function of Pinia, but is exactly the same. Today’s article will introduce this pineapple to you.

The installation

In the existing project, the following command was used to install the Pinia module.

# yarn
yarn add pinia@next
# npm
npm i pinia@next
Copy the code

After the Vue3 installation is complete, import and install the Vue3 project from the entry file.

// main.js import {createApp} from 'vue' import {createPinia} from 'pinia' import App from './ app.vue '// instantiate vue Const app = createApp(app) // Install Pinia app.use(createPinia()) // Mount real DOM app.mount('#app')Copy the code

Get started

To use Pinia, you simply define a store and import the data where it is used.

Define the Store

Import {defineStore} from "pinia" // Expose a use method to the outside, Const useCounterStore = defineStore({// The id of each store must be unique: 'counter', // state means data source state: () => ({count: 0}), // getters is similar to computed twice for the value of state. {double () {// this in the getter refers to 👉 state return this.count * 2}, // We can get the state double in the first argument of the function: (state) => {return state.count * 2}}, // actions {increment() {// This in action points to 👉 state this.count++},}}) export default useCounterStoreCopy the code

In addition to building state in the vuex-like manner described above, you can also create a store in the form of a function, somewhat similar to setup() in Vue3.

Import {ref, computed} from "vue" import {defineStore} from "pinia" // Expose a use method externally, This method will export the state const useCounterStore = defineStore('counter', function () { const count = ref(0) const double = computed(() => count.value * 2) function increment() { count.value++ }  return { count, double, increment } }) export default useCounterStoreCopy the code

The use of the Store

As mentioned earlier, Pinia provides two ways to use the Store, Options Api, and Composition Api, all perfectly supported.

Options Api

In the Options Api, you can directly use the official mapActions and mapState methods to export the state, getter, and action in the store. Its usage is basically the same as Vuex, and it is easy to use.

import { mapActions, mapState } from 'pinia' import { useCounterStore } from '.. /model/counter' export default { name: 'HelloWorld', computed: { ... mapState(useCounterStore, ['count', 'double']) }, methods: { ... mapActions(useCounterStore, ['increment']) } }Copy the code

Composition Api

In the Composition Api, both the state and the getter need to listen for changes through computed methods, just as in the Options Api, you need to put changes in computed objects. In addition, the state value obtained from the Options Api can be directly modified. Of course, it is recommended to write an action to operate the state value, which is convenient for later maintenance.

// Composition Api import { computed } from 'vue' import { useCounterStore } from '.. /stores/counter' export default { name: 'HelloWorld', setup() {const counter = useCounterStore() return {// Both state and getter need to use computed, This is the same as the Options Api Count: computed(() => counter. Count), double: computed(() => counter. Double), increment: Increment: counter. Increment () {counter. Count++}, increment: counter. Increment ();Copy the code

Type hinting

In Vuex, TypeScript type hints are not very good, and only its state can be found when type derivation is performed. Especially in the process of writing code, code hints are not smart.

Pinia, on the other hand, can derive all the states, getters, and actions that are defined, making it much easier to write code.

The main thing is that Pinia has very friendly type definitions in TypeScript. If you are interested, check out pinia’s type definition file (Pinia.d.ts) :

The code segment

Because of the modular design, all stores can be imported individually, rather than being mounted to a store via Modules, as vuex does.

Assume that we have created a Store through Vuex with two modules: User and Goods. Even if the current home page only uses user information, the entire Store is packaged into the JS chunk of the home page.

If we were using Pinia, we would use defineStore to define two stores that were completely separate, and the two pages would not affect each other when they were introduced. At the end of packaging, JS chunk of the home page and JS chunk of the commodity page will package corresponding stores respectively.


So much for Pinia. If you are currently developing a new project using Vue3, it is recommended to use Pinia mindless, which is much simpler and only 1KB in size.