4

It has been a while since Vue3 was released. It adopted a new responsive system and built a brand new set of Composition API . The surrounding ecology of Vue is stepping up to adapt to this new system, and the official state management library Vuex is also being adapted. For this reason, the official proposed a new proposal of Vuex 5

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

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

Coincidentally, Vuex5's proposal cannot be said to have nothing to do with the functions implemented by Pinia. It can only be said to be exactly the same. Today's article will introduce you to this pineapple.

Install

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

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

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

// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

// 实例化 Vue
const app = createApp(App)
// 安装 Pinia
app.use(createPinia())
// 挂载在真实 DOM
app.mount('#app')

Get started

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

Define Store

import { defineStore } from "pinia"

// 对外部暴露一个 use 方法,该方法会导出我们定义的 state
const useCounterStore = defineStore({
  // 每个 store 的 id 必须唯一
  id: 'counter',
  // state 表示数据源
  state: () => ({
    count: 0
  }),
  // getters 类似于 computed,可对 state 的值进行二次计算
  getters: {
    double () {
        // getter 中的 this 指向👉 state
        return this.count * 2
      },
      // 如果使用箭头函数会导致 this 指向有问题
      // 可以在函数的第一个参数中拿到 state
    double: (state) => {
        return state.count * 2
      }
  },
  // actions 用来修改 state
  actions: {
    increment() {
      // action 中的 this 指向👉 state
      this.count++
    },
  }
})

export default useCounterStore

In addition to using the above-mentioned vuex-like way to build state, you can also use function to create a store, which is a bit similar to 061b9c3c056f1b in setup() .

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

// 对外部暴露一个 use 方法,该方法会导出我们定义的 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 useCounterStore

Use Store

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

Options Api

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

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

Composition Api , both state and getter need to monitor changes computed method, which is the same as the Options Api , which needs to be placed in the computed In addition, Options Api in 061b9c3c057032 can be directly modified. Of course, it is recommended to write an action to manipulate the state value to facilitate subsequent maintenance.

// Composition Api
import { computed } from 'vue'
import { useCounterStore } from '../stores/counter'
export default {
  name: 'HelloWorld',
  setup() {
    const counter = useCounterStore()
    return {
      // state 和 getter 都需要在使用 computed,这和 Options Api 一样
      count: computed(() => counter.count),
      double: computed(() => counter.double),
      increment: () => { counter.count++ }, // 可以直接修改 state 的值
      increment: counter.increment, // 可以引用 store 中定义的 action
    }
  }
}

Type hint

In Vuex, TypeScript's type hints are not very well done. When performing type inference, only its state can be found. Especially in the process of writing code, code hints are very unintelligent.

And pinia can derive all the defined state, getter, and action, which will be much more convenient when writing code.

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

Code split

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

Suppose, we currently create a Store through Vuex, and there are two modules under this Store, namely the user module (User) and the commodity module (Goods). Even if the current homepage only uses user information, the entire Store will be packaged into the js chunk of the homepage.

If we use pinia, we will use defineStore define two stores that are completely separated. When the two pages are introduced, they will not affect each other. When finally packaging, the js chunk on the homepage and the js chunk on the product page will be packaged in the corresponding store respectively.


This is the end of Pinia's introduction. If there is a new project to use Vue3 for development, it is recommended to use Pinia without a brain, which is more concise and only 1KB in size.


Shenfq
4k 声望6.8k 粉丝