Pinia Quick Start

Preface

Vue3 has been launched for a long time, and the ecology around it is becoming more and more complete. When we used Vue2 before, Vuex was a must-have. As a state management tool, it brought us great convenience. After the launch of Vue3, although many things have changed compared to Vue2, the core things have remained the same, such as state management, routing, etc. Regarding Vue3, You Dashen recommended that we use pinia to achieve state management. He also said that pinia is the new version of Vuex.

So what exactly is pinia? This article will help you learn about it!

1.What is pinia?

If you have learned Vue2, then you must have used Vuex. We all know that Vuex mainly plays the role of state management in Vue2. The so-called state management is simply a place to store data. The data stored in Vuex can be accessed in each component. It is an important part of the Vue ecosystem. component.

Since Vuex is so important, how can it be discarded in Vue3?

In Vue3, you can use traditional Vuex to implement state management, or you can use the latest pinia to implement state management. Let's take a look at how the official website explains pinia.

Official website explanation:

Pinia is a repository for Vue that allows you to share state across components/pages.

It is not difficult to see from the explanation on the official website above that pinia and Vuex have the same function. It also acts as a data store. The data stored in pinia allows us to use it in various components.

In fact, pinia is an upgraded version of Vuex. The official website also said that in order to respect the original author, it was named pinia instead of Vuex, so you can directly compare pinia to Vuex of Vue3.

2. Why use pinia?

Many friends are resistant to learning new things, such as the pinia we are talking about here. Many friends may raise a series of questions: Why should we learn pinia? What are the advantages of pinia? Since Vue3 can also use Vuex, why should I learn it? ...

Regarding the above series of questions, I believe that many friends who have just started learning pinia will have this question, including myself. Of course, these questions actually have answers. We can’t learn something for no reason! It definitely has its own advantages, so we will give the advantages of pinia here first, so that everyone can have an idea of ​​it. After you are proficient in using it, you will look at these advantages in retrospect. I believe you can understand.

advantage:

  • Both Vue2 and Vue3 are supported, which allows our friends who use both Vue2 and Vue3 to get started quickly.
  • There are only state, getter, and action in pinia, and Mutation in Vuex has been abandoned. Mutation in Vuex has never been very popular among friends, so Pinia simply abandoned it, which undoubtedly reduced our workload.
  • Action in Pinia supports synchronization and asynchronousness, but Vuex does not support it.
  • Good Typescript support. After all, our Vue3 recommends using TS for writing. At this time, using pinia is very suitable.
  • There is no need to create nested modules. If there is too much data in Vuex, we usually manage it in modules, which is a bit troublesome. In Pinia, each store is independent and does not affect each other.
  • The size is very small, only about 1KB.
  • pinia supports plug-ins to extend its functionality.
  • Supports server-side rendering.

There are many advantages of pinia. The main advantages listed above are some of its main advantages. More details need to be understood slowly when you use it.

3. Preparation

If you want to learn pinia, it is best to have a foundation of Vue3 and understand what the combined API is. If you don’t know Vue3 yet, it is recommended to learn Vue3 first.

When this article explains pinia, it is all based on Vue3. As for how to use pinia in Vue2, friends can go to the pinia official website to learn by themselves. After all, there are still a few people using pinia in Vue2.

Project construction:

We build a latest Vue3 + TS + Vite project here.

Excuting an order:

npm create vite@latest my-vite-app --template vue-ts

Run the project:

npm install npm run dev

Delete other useless code in app.vue. The final page is as follows:

0

4.Basic use of pinia

4.1 Install pinia

Like vue-router, vuex, etc., if we want to use pinia, we need to install it first, and installing it is relatively simple.

Installation command:

yarn add pinia # Or use npm npm install pinia

After the installation is complete, we need to mount pinia into the Vue application, which means we need to create a root storage and pass it to the application. Simply put, we create a bucket to store data and put it in the application.

Modify main.js, introduce the createPinia method provided by pinia, and create root storage.

code show as below:

// main.ts import { createApp } from "vue"; import App from "./App.vue"; import { createPinia } from "pinia"; const pinia = createPinia(); const app = createApp(App); app.use(pinia); app.mount("#app");

4.2 Create store

Store simply means data warehouse, and all our data is placed in the store. Of course, you can also understand it as a public component, but this public component only stores data, which can be accessed and modified by all our other components.

We need to use the defineStore() method provided by pinia to create a store, which is used to store the data we need to use globally.

First, create a new store folder in the project src directory to store the various stores we created. Then create a new user.ts file in this directory, which is mainly used to store user-related stores.

code show as below:

/src/store/user.ts import { defineStore } from 'pinia' // The first parameter is the unique id of the store in the application export const useUsersStore = defineStore('users', { // Other configuration items})

Creating a store is very simple. Just call the defineStore function in pinia. This function receives two parameters:

  • name: a string, a required item, the unique ID of the store.
  • options: an object, store configuration items, such as configuring data in the store, methods to modify data, etc.

We can define any number of stores, because in fact, a store is a function. This is also one of the benefits of pinia, which flattens our code. This is the same as the implementation idea of ​​Vue3.

4.3 Using store

We created a store earlier. To put it bluntly, we created a method, so our purpose must be to use it. If we want to use it in App.vue, how should we use it?

code show as below:

/src/App.vue <script setup lang="ts"> import { useUsersStore } from "../src/store/user"; const store = useUsersStore(); console.log(store); </script>

Using the store is very simple. Just introduce the useUsersStore method we declared. We can first take a look at what is output when executing this method:

0

4.4 Add state

We all know that the store is used to store public data, so where exactly does the data exist? Earlier we used the defineStore function to create a store. The second parameter of this function is an options configuration item. The data we need to store is placed in the state attribute in the options object.

Suppose we add some basic task data to the store and modify the user.ts code.

code show as below:

export const useUsersStore = defineStore("users", { state: () => { return { name: "Little Pig Classroom", age: 25, sex: "Male", }; }, });

In the above code, we added the state attribute to the configuration item, which is used to store data. We added 3 pieces of data to the state. It should be noted that state receives the value returned by an arrow function, and it cannot directly receive an object.

4.5 Operation state

The purpose of storing data in the store is to operate it, so we will try to operate the data in the state next.

4.5.1 Read state data

Reading state data is very simple. We have tried printing the store in App.vue before, so let’s add the data and then look at the printing results:

0

At this time, we found that there were a few more attributes in the printed results, which happened to be the data we added. We modified App.vue to display these data.

code show as below:

<template> <img alt="Vue logo" src="./assets/logo.png" /> <p>姓名:{ { name }}</p> <p>年龄:{ { age }}</p> <p>性别:{ { sex }}</p> </template> <script setup lang="ts"> import { ref } from "vue"; import { useUsersStore } from "../src/store/user"; const store = useUsersStore(); const name = ref<string>(store.name); const age = ref<number>(store.age); const sex = ref<string>(store.sex); </script>

Output result:

0

In the above code, we directly obtain the value stored in the store through store.age, etc., but have you noticed that this is more cumbersome. We can actually use destructuring to obtain the value, making the code more concise.

The deconstructed code is as follows:

import { useUsersStore } from "../src/store/user"; const store = useUsersStore(); const { name, age, sex } = store;

The effect achieved by the above code is the same as that obtained one by one, but the code is much simpler.

4.5.2 Multiple components use state

The most important purpose of using store is to share data between components, so next we create a new child.vue component and use state data inside this component.

The child.vue code is as follows:

<template> <h1>I am a child component</h1> <p>Name: { { name }}</p> <p>Age: { { age }}</p> <p>Gender: { { sex }}</p> </template> <script setup lang="ts"> import { useUsersStore } from "../src/store/user"; const store = useUsersStore(); const { name, age, sex } = store; </script>

The child component is almost the same as the app.vue component, except that it simply uses the data in the store.

Realization effect:

0

In this way, we can achieve multiple components using the data in the store at the same time.

4.5.3 Modify state data

If we want to modify the data in the store, we can directly reassign the value. We add a button in App.vue and click the button to modify a certain data in the store.

code show as below:

<template> <img alt="Vue logo" src="./assets/logo.png" /> <p>姓名:{ { name }}</p> <p>年龄:{ { age }}</p> <p>性别:{ { sex }}</p> <button @click="changeName">更改姓名</button> </template> <script setup lang="ts"> import child from './child.vue'; import { useUsersStore } from "../src/store/user"; const store = useUsersStore(); const { name, age, sex } = store; const changeName = () => { store.name = "张三"; console.log(store); }; </script>

The above code adds a changeName method, which changes the value of name in the store. Let's click the button to see the final effect:

0

We can see that the name in the store has indeed been modified, but there seems to be no change on the page, which shows that the name we use is not responsive.

Many friends may say that you can use the listening function to monitor store changes and refresh the page...

In fact, pinia provides us with a method to make the name and other attributes we obtain responsive, and we re-modify the code.

The app.vue and child.vue codes are modified as follows:

import { storeToRefs } from 'pinia'; const store = useUsersStore(); const { name, age, sex } = storeToRefs(store);

The way of obtaining state data in our two components has been changed to the form of the above code, using pinia's storeToRefs function to make the data in sstate responsive.

In addition, we also add methods for changing state data to child.vue.

The child.vue code is as follows:

<template> <h1>I am a child component</h1> <p>Name: { { name }}</p> <p>Age: { { age }}</p> <p>Gender: { { sex }}</p> <button @click="changeName">Change name</button> </template> <script setup lang="ts"> import { useUsersStore } from "../src/store/user"; import { storeToRefs } from 'pinia'; const store = useUsersStore(); const { name, age, sex } = storeToRefs(store); const changeName = () => { store.name = "Little Pig Classroom"; }; </script>

At this time, let's try to click the buttons of the two components separately. The effect is as follows:

0

When the data in our store changes, the page is also updated!

4.5.4 Reset state

Sometimes we modify the state data and want to restore it. What should we do at this time? For example, the user fills out part of the form and suddenly wants to reset it to the original state.

At this point, we can directly call the store's $reset() method, continue to use our example, and add a reset button.

code show as below:

<button @click="reset">Reset store</button> // Reset store const reset = () => { store.$reset(); };

When we click the reset button, the data in the store will change to the initial state and the page will be updated.

4.5.5 Batch change state data

Previously, we modified the state data one by one, such as store.name="Zhang San", etc. If we need to modify many pieces of data at one time, there is an easier way to use the store's $patch method. Modify the app.vue code and add a method to change data in batches.

code show as below:

<button @click="patchStore">Batch modify data</button> // Batch modify data const patchStore = () => { store.$patch({ name: "Zhang San", age: 100, sex: "Female ", }); };

Experienced friends may have discovered that our batch change method seems a bit expensive. If some fields in our state do not need to be changed, but according to the way the above code is written, we must enumerate all fields in the state. Out.

In order to solve this problem, the $patch method provided by pinia can also receive a callback function. Its usage is a bit like our array loop callback function.

The sample code is as follows:

store.$patch((state) => { state.items.push({ name: 'shoes', quantity: 1 }) state.hasChanged = true })

In the above code, we changed the state data in batches without listing all the state fields.

4.5.6 Directly replace the entire state

Pinia provides a method that allows us to directly replace the entire state object, using the store's $state method.

Sample code:

store.$state = { counter: 666, name: 'Zhang San' }

The above code will replace the state we declared in advance with a new object. This scenario may be used less often, so I will not explain it here.

4.6 getters attribute

Getters are another attribute in the defineStore parameter configuration item. We talked about the state attribute earlier. The getter attribute value is an object, which contains various methods. You can think of getter as a computed property in Vue. Its function is to return a new result. Since it is similar to a computed property in Vue, it will definitely be cached, just like computed.

Of course, our getter here is to process state data.

4.6.1 Add getter

Let’s first take a look at how to define the getter and modify user.ts.

code show as below:

export const useUsersStore = defineStore("users", { state: () => { return { name: "小猪课堂", age: 25, sex: "男", }; }, getters: { getAddAge: (state) => { return state.age + 100; }, }, });

In the above code, we added the getter attribute to the configuration item parameter. The attribute object defines a getAddAge method. This method will receive a state parameter by default, which is the state object, and then the method returns a new data.

4.6.2 Using getters

We have defined the getter in the store, so how to use it in the component? It is very simple to use, we modify App.vue.

code show as below:

<template> <p>New age: { { store.getAddAge }}</p> <button @click="patchStore">Batch modify data</button> </template> <script setup lang="ts"> import { useUsersStore } from "../src/store/user"; const store = useUsersStore(); // Modify data in batches const patchStore = () => { store.$patch({ name: "Zhang San", age: 100, sex: "female", }); }; </script>

In the above code, we used the store.gettAddAge method directly on the label, which can ensure responsiveness. In fact, the name and other attributes in our state can also be used directly on the label in this way, and can also maintain responsiveness.

When we click the batch edit data button, the new age field on the page will also change.

4.6.3 Calling other getters within a getter

Previously, our getAddAge method simply used the state method, but sometimes we need to call other getter methods in this getter method. How to call it at this time?

In fact, it is very simple. We can call this directly in the getter method. This points to the store instance, so of course other getters can be called.

The sample code is as follows:

export const useUsersStore = defineStore("users", { state: () => { return { name: "Little Pig Classroom", age: 25, sex: "Male", }; }, getters: { getAddAge: (state) => { return state.age + 100; }, getNameAndAge(): string { return this.name + this.getAddAge; // Call other getters }, }, });

In the above code, we defined a getter function named getNameAndAge, and used this directly inside the function to obtain state data and call other getter functions.

Careful friends may find that we do not use the form of arrow functions here. This is because we use this inside the function. I believe everyone knows about the this pointing problem of arrow functions! So here we don't use the arrow function form.

Then there is no change in the form of calling in the component. The code is as follows:

<p>Call other getters: { { store.getNameAndAge }}</p>

4.6.4 Getter passing parameters

Since the getter function does some calculations or processing, we will most likely need to pass parameters to the getter function, but we said earlier that the getter function is equivalent to the computed property of the store, which is similar to the computed property of vue, so we all know that calculations in Vue Attributes cannot pass parameters directly, so if our getter function here wants to accept parameters, it also needs to be processed.

Sample code:

export const useUsersStore = defineStore("users", { state: () => { return { name: "Little Pig Classroom", age: 25, sex: "Male", }; }, getters: { getAddAge: (state) => { return (num: number) => state.age + num; }, getNameAndAge(): string { return this.name + this.getAddAge; // Call other getters }, }, });

In the above code, our getter function getAddAge receives a parameter num. This writing method actually has a concept of closure in it. It is equivalent to us returning a new function as a whole and passing state into the new function.

Next we use it in the component. The method is very simple. The code is as follows:

<p>New age: { { store.getAddAge(1100) }}</p>

4.7 actions attribute

The state and getters attributes we mentioned earlier are mainly at the data level and have no specific business logic code. They are the same as the data data and computed properties in our component code.

Then, if we have business code, it is best to unload the actions attribute. This attribute is similar to the methods in our component code and is used to place some methods for processing business logic.

The actions attribute value is also an object, which also stores various methods, including synchronous methods and asynchronous methods.

4.7.1 Add actions

We can try adding an actions method and modify user.ts.

code show as below:

export const useUsersStore = defineStore("users", { state: () => { return { name: "小猪课堂", age: 25, sex: "男", }; }, getters: { getAddAge: (state) => { return (num: number) => state.age + num; }, getNameAndAge(): string { return this.name + this.getAddAge; // 调用其它getter }, }, actions: { saveName(name: string) { this.name = name; }, }, });

In the above code, we defined a very simple actions method. In actual scenarios, this method can be any logic, such as sending requests, storing tokens, etc. You can treat the actions method as an ordinary method. The special thing is that this inside the method points to the current store.

4.7.2 Using actions

It is also very simple to use the methods in actions. For example, we want to call this method in App.vue.

code show as below:

const saveName = () => { store.saveName("I am a little pig"); };

We click the button and directly call the actions method in the store.

5. Summary of sample code

The codes in the previous chapters are not complete, and the main code parts are posted. In this section, we will post all the codes used in this article for everyone to practice.

main.ts code:

import { createApp } from "vue"; import App from "./App.vue"; import { createPinia } from "pinia"; const pinia = createPinia(); const app = createApp(App); app.use(pinia); app.mount("#app");

user.ts code:

import { defineStore } from "pinia"; // The first parameter is the unique id of the store in the application export const useUsersStore = defineStore("users", { state: () => { return { name: "Little Pig Classroom" , age: 25, sex: "male", }; }, getters: { getAddAge: (state) => { return (num: number) => state.age + num; }, getNameAndAge(): string { return this .name + this.getAddAge; // Call other getters }, }, actions: { saveName(name: string) { this.name = name; }, }, });

App.vue code:

<template> <img alt="Vue logo" src="./assets/logo.png" /> <p>Name: { { name }}</p> <p>Age: { { age }}</ p> <p>Gender: { { sex }}</p> <p>New age: { { store.getAddAge(1100) }}</p> <p>Calling other getters: { { store.getNameAndAge }}</p> <button @click="changeName">Change name</button> <button @click="reset">Reset store</button> <button @click="patchStore"> Modify data in batches</button> <button @click="saveName">Call aciton</button> <!-- Subcomponent--> <child></child> </template> <script setup lang="ts" > import child from "./child.vue"; import { useUsersStore } from "../src/store/user"; import { storeToRefs } from "pinia"; const store = useUsersStore(); const { name, age, sex } = storeToRefs(store); const changeName = () => { store.name = "Zhang San"; console.log(store); }; // Reset store const reset = () => { store.$ reset(); }; // Modify data in batches const patchStore = () => { store.$patch({ name: "Zhang San", age: 100, sex:"Female", }); }; // Call the actions method const saveName = () => { store.saveName("I am a little pig"); }; </script>

child.vue code:

<template> <h1>I am a child component</h1> <p>Name: { { name }}</p> <p>Age: { { age }}</p> <p>Gender: { { sex }}</p> <button @click="changeName">Change name</button> </template> <script setup lang="ts"> import { useUsersStore } from "../src/store/user"; import { storeToRefs } from 'pinia'; const store = useUsersStore(); const { name, age, sex } = storeToRefs(store); const changeName = () => { store.name = "Little Pig Classroom"; }; </script>

Summarize

There are very few knowledge points in pinia. If you have a basic knowledge of Vuex, it will be even easier to learn. In fact, what we should pay more attention to is its function idea. Have you noticed that everything we do in Vue3 seems to be represented by a function. Pinia also continues this idea.

Therefore, it is more important for everyone to understand this idea of ​​combined programming. Pinia is nothing more than the following three major points:

  • state
  • getters
  • actions

Of course, this article only explains the basic usage part, but it can meet most needs in actual work. If you are still interested in learning other features of pinia, such as plug-ins, subscriptions, etc., you can go to the official website: pinia official website .

Guess you like

Origin blog.csdn.net/weixin_62635213/article/details/132688289