ホームページ  >  記事  >  ウェブフロントエンド  >  Vue の新しい状態管理 Pinia を使い始める方法については、この記事をお読みください。

Vue の新しい状態管理 Pinia を使い始める方法については、この記事をお読みください。

青灯夜游
青灯夜游転載
2022-03-18 11:14:312391ブラウズ

Pinia は Vue によって開発された新しい状態管理ライブラリですが、初心者はどのようにして Pinia を使い始めることができますか?次の記事では、Pinia について紹介し、その主要な機能と簡単な使い方を紹介します。

Vue の新しい状態管理 Pinia を使い始める方法については、この記事をお読みください。

Vuex は、誰もがよく知っている古い Vue 状態管理ライブラリです。

Pinia は、Vue のメンバーによって Vue 専用に開発されたまったく新しいライブラリです。 js チーム状態管理ライブラリであり、公式 github

に含まれています。Vuex があるのに、なぜ別の Pinia を開発する必要があるのでしょうか?

まず写真を撮って、当時の Vuex5 の提案書 を見てみましょう。これは次世代 Vuex5 がどうあるべきかです。 [関連する推奨事項: vuejs ビデオ チュートリアル ]

Vue の新しい状態管理 Pinia を使い始める方法については、この記事をお読みください。

Pinia は、当時の Vuex5 提案で言及された機能点に完全に準拠しているため、次のように言えます。そのPinia 作者が正式な開発者であり、正式に引き継がれているため、Vuex5であると言っても過言ではありませんが、現在はVuexとPiniaはまだ2つの独立したウェアハウスであり、将来的には統合または独立して開発される可能性があります、しかし、それらは間違いなく公式によって推奨されています最も良いのはPoniaです

Vue3でVuexを使用する場合、Vuex4を使用する必要がありますが、これは過渡的な選択肢としてのみ使用でき、大きな欠陥があります。新しい状態管理である Componition API の誕生により、Pinia が設計されました。

Pinia と Vuex

Vuex: State, Gettes ミューテーション(同期)、アクション(非同期)

ピニア状態 GettesActions(同期、非同期、すべてサポート)

Vuex の最新バージョンは

4.xx

    Vue3 用の Vuex4
  • Vue2 用 Vuex3
Ponia の最新バージョンは

2.xx

    Vue2 と Vue3 の両方をサポートします
現時点では、Pinia は Vuex よりもはるかに優れています。Vuex の多くの問題が解決されるため、特に TypeScript プロジェクトの場合は、Pinia を直接使用することを強くお勧めします。

Pinia のコア機能

    Pinia には
  • Mutations
  • Actions 同期および非同期をサポート
  • モジュールなしのネスト構造
    • Pinia はフラットを提供します設計による構造。これは、各ストアが互いに独立しており、誰も誰にも属さないことを意味します。つまり、フラットで、コードがより適切に分離され、名前空間がありません。もちろん、1 つのモジュールに別のモジュールをインポートすることでストアを暗黙的にネストすることもでき、ストアの循環依存関係を持つこともできます
  • Better
  • TypeScript Support
      TypeScript をサポートするカスタムの複雑なラッパーを作成する必要はありません。すべてが型付けされており、API は可能な限り TS 型推論を使用するように設計されています
  • 注入、関数のインポート、呼び出しは必要ありません自動補完を活用して開発をより便利にしてください。
  • ストアを手動で追加する必要はありません。そのモジュールは作成時にデフォルトで自動的に登録されます。
  • Vue2 どちらも Vue3 と
  • をサポートしています。
      初期インストールと SSR 構成を除き、両方で使用される API は同じです
  • サポート
  • Vue DevTools
      Vue DevTools
    • のタイムラインを追跡します。アクションとミューテーション
    • #モジュールを使用するコンポーネントでモジュール自体を観察できます
    • #デバッグを容易にするタイムトラベルをサポート
    • Vue2 では、Ponia は次のすべてのインターフェイスを使用します。 Vuex であるため、併用することはできません
    • しかし、Vue3 のデバッグ ツールのサポートは十分ではありません。たとえば、タイムトラベル機能はありません
  • ホット モジュールupdate
    • ページを再ロードせずにモジュールを変更できます
    • ホット アップデート中は既存のステータスが維持されます
  • サポート プラグインを使用して拡張しますPinia 関数
  • サーバー側レンダリングのサポート
Pinia の使用

例として

Vue3 TypeScript を取り上げます

インストール

npm install pinia

main.ts 初期設定

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

ストア ディレクトリに

user.ts を作成します。たとえば、最初に名前を定義してエクスポートします。 user

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

defineStore のモジュールは 2 つのパラメータを受け取ります

最初のパラメータはモジュールの名前であり、一意で複数のモジュールである必要があります。同じ名前を持つことはできません。Ponia はすべてのモジュールをルート コンテナにマウントします

2 番目のパラメータはオブジェクトで、内部のオプションは Vuex と似ています

  • 其中 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,而且可以手动修改数据调试,非常方便

Vue の新しい状態管理 Pinia を使い始める方法については、この記事をお読みください。

模拟调用接口

示例:

我们先定义示例接口 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前端

以上がVue の新しい状態管理 Pinia を使い始める方法については、この記事をお読みください。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。