Heim  >  Artikel  >  Web-Frontend  >  Wie Sie mit Vues neuem Staatsmanagement Pinia beginnen, lesen Sie diesen Artikel!

Wie Sie mit Vues neuem Staatsmanagement Pinia beginnen, lesen Sie diesen Artikel!

青灯夜游
青灯夜游nach vorne
2022-03-18 11:14:312314Durchsuche

Pinia ist eine neue Staatsverwaltungsbibliothek, die von Vue entwickelt wurde. Wie können Einsteiger also mit Pinia beginnen? Der folgende Artikel stellt Ihnen Pinia vor und stellt seine Kernfunktionen und die einfache Verwendung vor. Ich hoffe, er wird Ihnen hilfreich sein!

Wie Sie mit Vues neuem Staatsmanagement Pinia beginnen, lesen Sie diesen Artikel!

Vuex ist eine alte Vue-Zustandsverwaltungsbibliothek, die jeder kennt.

Pinia ist eine brandneue Zustandsverwaltungsbibliothek, die speziell für Vue von Mitgliedern des Vue.js-Teams entwickelt und in den offiziellen github aufgenommen wurde

Warum müssen wir Pinia entwickeln, wenn wir bereits Vuex haben?

Machen wir zunächst ein Foto, um uns den Vorschlag für Vuex5 anzusehen, wie die nächste Generation von Vuex5 aussehen soll. [Verwandte Empfehlung: vuejs Video-Tutorial]

Wie Sie mit Vues neuem Staatsmanagement Pinia beginnen, lesen Sie diesen Artikel!

Pinia entspricht vollständig den in seinem damaligen Vuex5-Vorschlag genannten Funktionspunkten, daher ist es keine Übertreibung zu sagen, dass Pinia Vuex5 ist, da sein Autor offizieller Entwickler ist , und wurde offiziell übernommen, aber derzeit sind Vuex und Pinia noch zwei unabhängige Lagerhäuser. Sie können in Zukunft zusammengeführt oder unabhängig voneinander entwickelt werden, aber die offizielle Empfehlung ist Pinia

, da Sie Vuex nur in Vue3 und Vuex4 verwenden können Wird als Übergangslösung verwendet und weist große Mängel auf. Daher wurde nach der Geburt der Componsition-API eine neue Zustandsverwaltung Pinia

Pinia und Vuex

Vuex entworfen: State, Gettes, Mutationen (synchron), Aktionen (asynchron)StateGettesMutations(同步)、Actions(异步)

PiniaStateGettesActions(同步异步都支持)

Vuex 当前最新版是 4.x

  • Vuex4 用于 Vue3
  • Vuex3 用于 Vue2

Pinia 当前最新版是 2.x

  • 即支持 Vue2 也支持 Vue3

就目前而言 Pinia 比 Vuex 好太多了,解决了 Vuex 的很多问题,所以笔者也非常建议直接使用 Pinia,尤其是 TypeScript 的项目

Pinia 核心特性

  • Pinia 没有 Mutations
  • Actions 支持同步和异步
  • 没有模块的嵌套结构
    • Pinia 通过设计提供扁平结构,就是说每个 store 都是互相独立的,谁也不属于谁,也就是扁平化了,更好的代码分割且没有命名空间。当然你也可以通过在一个模块中导入另一个模块来隐式嵌套 store,甚至可以拥有 store 的循环依赖关系
  • 更好的 TypeScript 支持
    • 不需要再创建自定义的复杂包装器来支持 TypeScript 所有内容都类型化,并且 API 的设计方式也尽可能的使用 TS 类型推断
  • 不需要注入、导入函数、调用它们,享受自动补全,让我们开发更加方便
  • 无需手动添加 store,它的模块默认情况下创建就自动注册的
  • Vue2 和 Vue3 都支持
    • 除了初始化安装和SSR配置之外,两者使用上的API都是相同的
  • 支持 Vue DevTools
    • 跟踪 actions, mutations 的时间线
    • 在使用了模块的组件中就可以观察到模块本身
    • 支持 time-travel 更容易调试
    • 在 Vue2 中 Pinia 会使用 Vuex 的所有接口,所以它俩不能一起使用
    • 但是针对 Vue3 的调试工具支持还不够完美,比如还没有 time-travel 功能
  • 模块热更新
    • 无需重新加载页面就可以修改模块
    • 热更新的时候会保持任何现有状态
  • 支持使用插件扩展 Pinia 功能
  • 支持服务端渲染

Pinia 使用

Vue3 + TypeScript 为例

安装

npm install pinia

main.ts 初始化配置

import { createPinia } from 'pinia'createApp(App).use(createPinia()).mount('#app')

在 store 目录下创建一个 user.ts 为例,我们先定义并导出一个名为 user 的模块

import { defineStore } from 'pinia'
export const userStore = defineStore('user', {
    state: () => {
        return { 
            count: 1,
            arr: []
        }
    },
    getters: { ... },
    actions: { ... }
})

defineStore

Pinia
: Zustand, Gettes code>, Aktionen (sowohl synchrone als auch asynchrone Aktionen werden unterstützt)

🎜Die neueste Version von Vuex ist 4.x🎜
  • Vuex4 wird für Vue3
  • Vuex3 wird für Vue2 verwendet
🎜Die neueste Version von Pinia ist 2.x🎜
  • Es unterstützt sowohl Vue2 als auch Vue3
li>🎜Im Moment ist Pinia viel besser als Vuex und löst viele Probleme von Vuex, daher empfehle ich dringend, Pinia direkt zu verwenden, insbesondere für TypeScript-Projekte🎜

Pinia-Kernfunktionen🎜
  • Pinia hat keine Mutationen
  • Aktionen unterstützt Synchronisation und Asynchron
  • Keine verschachtelte Modulstruktur
    • Pinia bietet durch das Design eine flache Struktur, was bedeutet, dass jeder Shop unabhängig voneinander ist und niemand zu irgendjemandem gehört. Es ist flach, mit besserer Code-Trennung und ohne Namensraum . . Natürlich können Sie den Store auch implizit verschachteln, indem Sie ein anderes Modul in ein Modul importieren, und sogar zirkuläre Abhängigkeiten des Stores haben.
  • Bessere TypeScript-Unterstützung
    • Es ist nicht erforderlich, einen benutzerdefinierten komplexen Wrapper zu erstellen, um TypeScript zu unterstützen. Der gesamte Inhalt ist typisiert und die API ist so konzipiert, dass sie so weit wie möglich TS-Typinferenz verwendet
  • Keine Notwendigkeit, Funktionen einzufügen, zu importieren, sie aufzurufen, die automatische Vervollständigung zu genießen, was unsere Entwicklung komfortabler macht
  • Der Store muss nicht manuell hinzugefügt werden, sein Modul wird standardmäßig automatisch registriert, wenn es erstellt wird
  • Sowohl Vue2 als auch Vue3 unterstützen
    • Mit Ausnahme der Erstinstallation und der SSR-Konfiguration ist die von beiden verwendete API dieselbe
  • Unterstützt Vue DevTools
    • Verfolgen der Zeitleiste von Aktionen und Mutationen
    • Das Modul selbst kann in den Komponenten beobachtet werden, die das Modul verwenden
    • Unterstützend Zeitreisen erleichtern das Debuggen
    • In Vue2 nutzt Pinia alle Schnittstellen von Vuex, sodass sie nicht zusammen verwendet werden können
    • Aber die Debugging-Tool-Unterstützung für Vue3 reicht nicht aus Perfekt, zum Beispiel Beispielsweise gibt es keine Zeitreisefunktion.
  • Modul-Hot-Update
    • Module können geändert werden, ohne die Seite neu zu laden
    • Hot-Update Jeder bestehende Zustand bleibt erhalten
  • Unterstützt die Verwendung von Plug-Ins zur Erweiterung der Pinia-Funktionen
  • Unterstützt serverseitiges Rendering
  • ul>

    Pinia verwendet 🎜🎜am Beispiel von Vue3 + TypeScript🎜🎜Installation🎜
    <template>
        <div>{{ user_store.count }}</div>
    </template>
    <script setup>
    import { userStore } from &#39;../store&#39;
    const user_store = userStore()
    // 解构
    // const { count } = userStore()
    </script>
    🎜main.ts-Initialisierungskonfiguration 🎜
    <template>
        <div>{{ count }}</div>
    </template>
    <script setup>
    import { storeToRefs } from &#39;pinia&#39;
    import { userStore } from &#39;../store&#39;
    const { count } = storeToRefs(userStore)
    </script>
    🎜im Store Erstellen Sie eine user.ts im Verzeichnis. Beispielsweise definieren und exportieren wir zunächst ein Modul mit dem Namen user 🎜
    <template>
        <div>{{ myCount }}</div>
        <div>{{ myCount }}</div>
        <div>{{ myCount }}</div>
    </template>
    🎜defineStore empfängt zwei Parameter 🎜🎜Der erste Parameter ist der Name des Moduls, der eindeutig sein muss. Pinia mountet nicht alle Module im Root-Container 🎜Der zweite Parameter ist ein Objekt und die Optionen im Inneren sind die gleichen wie bei Vuex Almost🎜
    • 其中 state 用来存储全局状态,它必须是箭头函数,为了在服务端渲染的时候避免交叉请求导致的数据状态污染所以只能是函数,而必须用箭头函数则为了更好的 TS 类型推导
    • getters 就是用来封装计算属性,它有缓存的功能
    • actions 就是用来封装业务逻辑,修改 state

    访问 state

比如我们要在页面中访问 state 里的属性 count

由于 defineStore 会返回一个函数,所以要先调用拿到数据对象,然后就可以在模板中直接使用了

<template>
    <div>{{ user_store.count }}</div>
</template>
<script setup>
import { userStore } from &#39;../store&#39;
const user_store = userStore()
// 解构
// const { count } = userStore()
</script>

比如像注释中的解构出来使用,是完全没有问题的,只是注意了,这样拿到的数据不是响应式的,如果要解构还保持响应式就要用到一个方法 storeToRefs(),示例如下

<template>
    <div>{{ count }}</div>
</template>
<script setup>
import { storeToRefs } from &#39;pinia&#39;
import { userStore } from &#39;../store&#39;
const { count } = storeToRefs(userStore)
</script>

原因就是 Pinia 其实是把 state 数据都做了 reactive 处理,和 Vue3 的 reactive 同理,解构出来的也不是响应式,所以需要再做 ref 响应式代理

getters

这个和 Vuex 的 getters 一样,也有缓存功能。如下在页面中多次使用,第一次会调用 getters,数据没有改变的情况下之后会读取缓存

<template>
    <div>{{ myCount }}</div>
    <div>{{ myCount }}</div>
    <div>{{ myCount }}</div>
</template>

注意两种方法的区别,写在注释里了

getters: {
    // 方法一,接收一个可选参数 state
    myCount(state){
        console.log(&#39;调用了&#39;) // 页面中使用了三次,这里只会执行一次,然后缓存起来了
        return state.count + 1
    },
    // 方法二,不传参数,使用 this
    // 但是必须指定函数返回值的类型,否则类型推导不出来
    myCount(): number{
        return this.count + 1
    }
}

更新和 actions

更新 state 里的数据有四种方法,我们先看三种简单的更新,说明都写在注释里了

<template>
    <div>{{ user_store.count }}</div>
    <button @click="handleClick">按钮</button>
</template>
<script setup>
import { userStore } from &#39;../store&#39;
const user_store = userStore()
const handleClick = () => {
    // 方法一
    user_store.count++
    
    // 方法二,需要修改多个数据,建议用 $patch 批量更新,传入一个对象
    user_store.$patch({
        count: user_store.count1++,
        // arr: user_store.arr.push(1) // 错误
        arr: [ ...user_store.arr, 1 ] // 可以,但是还得把整个数组都拿出来解构,就没必要
    })
    
    // 使用 $patch 性能更优,因为多个数据更新只会更新一次视图
    
    // 方法三,还是$patch,传入函数,第一个参数就是 state
    user_store.$patch( state => {
        state.count++
        state.arr.push(1)
    })
}
</script>

第四种方法就是当逻辑比较多或者请求的时候,我们就可以封装到示例中 store/user.ts 里的 actions 里

可以传参数,也可以通过 this.xx 可以直接获取到 state 里的数据,需要注意的是不能用箭头函数定义 actions,不然就会绑定外部的 this 了

actions: {
    changeState(num: number){ // 不能用箭头函数
        this.count += num
    }
}

调用

const handleClick = () => {
    user_store.changeState(1)
}

支持 VueDevtools

打开开发者工具的 Vue Devtools 就会发现 Pinia,而且可以手动修改数据调试,非常方便

Wie Sie mit Vues neuem Staatsmanagement Pinia beginnen, lesen Sie diesen Artikel!

模拟调用接口

示例:

我们先定义示例接口 api/user.ts

// 接口数据类型
export interface userListType{
    id: number
    name: string
    age: number
}
// 模拟请求接口返回的数据
const userList = [
    { id: 1, name: &#39;张三&#39;, age: 18 },
    { id: 2, name: &#39;李四&#39;, age: 19 },
]
// 封装模拟异步效果的定时器
async function wait(delay: number){
    return new Promise((resolve) => setTimeout(resolve, delay))
}
// 接口
export const getUserList = async () => {
    await wait(100) // 延迟100毫秒返回
    return userList
}

然后在 store/user.ts 里的 actions 封装调用接口

import { defineStore } from &#39;pinia&#39;
import { getUserList, userListType } from &#39;../api/user&#39;
export const userStore = defineStore(&#39;user&#39;, {
    state: () => {
        return {
            // 用户列表
            list: [] as userListType // 类型转换成 userListType
        }
    },
    actions: { 
        async loadUserList(){
            const list = await getUserList()
            this.list = list
        }
    }
})

页面中调用 actions 发起请求

<template>
    <ul>
        <li v-for="item in user_store.list"> ... </li>
    </ul>
</template>
<script setup>
import { userStore } from &#39;../store&#39;
const user_store = userStore()
user_store.loadUserList() // 加载所有数据
</script>

跨模块修改数据

在一个模块的 actions 里需要修改另一个模块的 state 数据

示例:比如在 chat 模块里修改 user 模块里某个用户的名称

// chat.ts
import { defineStore } from &#39;pinia&#39;
import { userStore } from &#39;./user&#39;
export const chatStore = defineStore(&#39;chat&#39;, {
    actions: { 
        someMethod(userItem){
            userItem.name = &#39;新的名字&#39;
            const user_store = userStore()
            user_store.updateUserName(userItem)
        }
    }
})

user 模块里

// user.ts
import { defineStore } from &#39;pinia&#39;
export const userStore = defineStore(&#39;user&#39;, {
    state: () => {
        return {
            list: []
        }
    },
    actions: { 
        updateUserName(userItem){
            const user = this.list.find(item => item.id === userItem.id)
            if(user){
                user.name = userItem.name
            }
        }
    }
})

(学习视频分享:vuejs教程web前端

Das obige ist der detaillierte Inhalt vonWie Sie mit Vues neuem Staatsmanagement Pinia beginnen, lesen Sie diesen Artikel!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen