[Vue3] new Vue3 status management tool: Pinia

[Vue3] new Vue3 status management tool: Pinia

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 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 we defined
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. It can calculate the value of state twice
  getters: {
    double () {
        // this in getter points to 👉  state
        return this.count * 2
      },
      // If the arrow function is used, it will lead to the problem of 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 above vuex like method to build a state, you can also use the form of function to create a store, which is a bit 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 we defined
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. Its 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 attaching all modules to one store through modules like vuex.

Suppose that we have created a Store through Vuex. There are two modules under the Store, namely, the User module and the Goods module. Even if the current home page only uses User information, the whole Store will be packaged into the js chunk of 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.

Pinia's introduction 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: Javascript Front-end TypeScript Vue.js

Added by Sakujou on Fri, 28 Jan 2022 01:08:22 +0200