New Vue3 status management tool: Pinia

Vue3 has been released for some time. It adopts a new responsive system and builds a new Composition API. The surrounding ecology of Vue is stepping up the adaptation of this new system, and the official state management library Vuex is also being adapted. Therefore, the official puts forward a Vuex 5 A new proposal.

  • Support two syntax to create Store: Options Api and Composition Api;
  • Delete mutations. Only state, getters and actions are supported;
  • Modular design, can well support code segmentation;
  • There are no nested modules, only the concept of Store;
  • Complete TypeScript support;

Below this proposal, there is an interesting comment. Simply translate:

Unfortunately, as like as two peas, unfortunately, Vuex5's proposal is not related to the functions of Pinia, but it can only be said to be the same. Today's article will introduce this pineapple to you.

install

In the existing project, the following commands have been used to install the Pinia module.

# yarn
yarn add pinia@next
# npm
npm i pinia@next

After installation, you need to import and install in the entry file of Vue3 project.

// 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 in real DOM
app.mount('#app')

Get started

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

Define Store

import { defineStore } from "pinia"

// Expose a use method to the outside, which will export the state defined by us
const useCounterStore = defineStore({
  // The id of each store must be unique
  id: 'counter',
  // state indicates the data source
  state: () => ({
    count: 0
  }),
  // getters is similar to computed and can perform secondary calculation on the value of state
  getters: {
    double () {
        // this in getter points to 👉  state
        return this.count * 2
      },
      // If you use the arrow function, there will be a problem with this pointing
      // You can get state in the first parameter of the function
    double: (state) => {
        return state.count * 2
      }
  },
  // actions is used to modify the state
  actions: {
    increment() {
      // this in action points to 👉  state
      this.count++
    },
  }
})

export default useCounterStore

In addition to using the vuex like method above to build a state, you can also use the form of function to create a store, which is somewhat similar to setup() in Vue3.

import { ref, computed } from "vue"
import { defineStore } from "pinia"

// Expose a use method to the outside, which will export the state defined by us
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 useCounterStore

Use Store

As mentioned earlier, Pinia provides two ways to use store, Options Api and Composition Api, which are perfectly supported.

Options Api

In Options Api, you can directly use the mapActions and mapState methods provided by the government to export the state, getter and action in the store. Their usage is basically the same as that of Vuex and 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'])
  }
}

Composition Api

In Composition Api, both state and getter need to monitor changes through the calculated method, which is the same as that in Options Api, which needs to be placed in the calculated object. In addition, the state value obtained in Options Api can be modified directly. Of course, it is recommended to write an action to operate the state value 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, which is the same as Options Api
      count: computed(() => counter.count),
      double: computed(() => counter.double),
      increment: () => { counter.count++ }, // You can directly modify the value of state
      increment: counter.increment, // You can reference the action s defined in the store
    }
  }
}

Type prompt

In Vuex, TypeScript's type prompt is not very good, and its state can only be found during type derivation. Especially in the process of writing code, the code prompt is not intelligent.

pinia can deduce all defined state s, getter s and action s, which will be much more convenient when writing code.

pinia has a very friendly type definition through TypeScript. If you are interested, you can see pinia's type definition file (pinia.d.ts):

Code segmentation

Due to the use of modular design, all stores can be introduced separately, instead of mounting all modules to one store through modules like vuex.

Suppose we create a Store through Vuex. There are two modules under the Store, namely, User module and Goods module. Even if only User information is used on the current home page, the whole Store will be packaged into js chunk on the home page.

If we use pinia, we will use defineStore to define two completely separate stores. When the two pages are introduced, they will not affect each other. Finally, when packaging, the js chunk on the home page and the js chunk on the product page will package the corresponding store respectively.

The introduction of Pinia has come to an end here. If there are new projects to be developed using Vue3, it is recommended to use Pinia without brain, which is more concise and only 1KB in size.

Keywords: Front-end Vue Vue.js

Added by aspbyte on Wed, 15 Dec 2021 14:59:49 +0200