浅いところから深いところまでVexを詳しく解説

序文

Vue を学習するとき、コンポーネント間の通信が必要になることがよくあります。コンポーネント間の通信方法としては、props を使用した親子通信、親コンポーネントを介した複数のサブコンポーネント間の通信、カスタム イベントを使用したサブコンポーネント間の通信 (ref を使用する方法もあります)、イベント バスなど、多くの既知の通信方法があります。 .

現在、イベントバスは非常に一般的な方法ですが、プロジェクトを実行するときにイベントバスが多すぎると面倒になり、コードが混乱しやすくなります。

このセクションでは、コンポーネント間の通信を実現するためのより簡単な方法を紹介します - vuex を使用して、上記の方法に対するこの方法の利点は、vuex を使用すると、すべてのコンポーネントが同じデータを一緒に操作できることです。これにより、通信の問題が回避されます。そして値を渡します。

1、Vuex を理解する

1.1 Vuexとは

Vuex は、Vue での集中状態 (データ) 管理を実装する Vue プラグインです. Vue アプリケーションで複数のコンポーネントの共有状態を集中管理 (読み書き) します. コンポーネント間の通信方法でもあり、適用可能な通信です任意のコンポーネント間。

上記の段落から抽出できるキーワードは次のとおりです。
状態 (データ)、管理、プラグイン

これらの 3 つの単語はより重要です。このうち、状態とデータの関係については後述しますが、管理とプラグインに関しては、上記の概念からわかるように、Vuex は実際には状態管理用のプラグインです。

したがって、Vuex の第一印象は、Vue で状態 (データ) を管理するために使用できるプラグインです。

1.2 Vuex の概要

Vuex はどのコンポーネントにも属していませんが、その内部データはデータを共有できます。各コンポーネントは、関連する API を使用して内部データを操作できます。

概略図は次のとおりです。
ここに画像の説明を挿入

1.3 Vuex 統合状態管理の利点

Vuex で共有データを一元管理できるため、開発と保守が容易です。

コンポーネント間のデータ共有を効率的に実現し、開発効率を向上させることができます。

Vuex に保存されたデータはレスポンシブであり、実際にデータをページと同期させることができます。

1.4 Vuex を使用する場合

通常、コンポーネント間で共有されるデータのみ vuex に保存する必要がありますが、コンポーネント内のプライベート データについては、コンポーネント自体のデータに保存されます。

次に、Vuex の構成

2.1 vuex 依存パッケージのインストールと vuex バージョンの問題

Vue2 では vuex3 バージョンを使用し、Vue3 では vuex4 バージョンを使用します。そうしないと、エラーが発生する可能性があります。

著者はここで vuex3 を使用します。

npm i vuex@3

2.2 vuex パッケージのインポート

vuex をダウンロードした後、vuex がプラグインであることも上記で紹介されているので、main.js に導入して登録する必要があります。

import Vuex from 'vuex'
Vue.use(Vuex)

2.3 ストア オブジェクトの作成

ここではまず、次の店舗オブジェクトを紹介します。店舗は倉庫として翻訳されます。store は、vuex での状態管理に使用されます。状態はデータとしても理解できます。

store は vuex の非常に重要な部分です。

ストア オブジェクトと関連コードを配置する js ファイルを作成する必要があります。

ここに画像の説明を挿入

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

export default new Vuex.Store({
    
    
    state: {
    
    },
    mutations: {
    
    },
    actions: {
    
    }
})

店内の物件は後ほど順次説明していきますが、最初に設定が必要です。

2.4 main.js にストアをマウントする

import Vue from 'vue'
import App from './App.vue'
import store from './store/index'

Vue.config.productionTip = false

new Vue({
    
    
  render: h => h(App),
  store
}).$mount('#app')

ここで、main.js の代わりに vuex が導入され、ストアに登録される理由を読者に説明したいと思います。まず、知る必要があります。ストアインスタンスを作成する前に、必ず Vue.use(Vuex) を使用してください、および js コードがコンパイルされると、 import で始まるものが最初にコンパイルされます。つまり、全部を main.js に入れる場合は、まず store インスタンスを作成してから、vuex を登録する必要があります。しかし、これは規則に準拠していないため、エラーが報告されます。
Uncaught Error: [vuex] must call Vue.use(Vuex) before creating a store instance

3、Vuexのコアコ​​ンセプト

このセクションでは、Vuex の中心的な概念を読者に説明するための小さなデモに焦点を当てます。

3.1 デモ

ケースは非常に単純です。数値をカウントとして設定し、2 つのコンポーネントを設定します。1 つのコンポーネントはカウントの加算と加算に使用され、もう 1 つのコンポーネントはカウントの減算と減算に使用されます。2 つのコンポーネントが連携してカウントを操作します。

私のコードでは、Jiafa と Jianfa の 2 つのコンポーネントをセットアップし、それらをアプリに配置しました。これが最初のデモの外観です。
ここに画像の説明を挿入
ここに画像の説明を挿入
次に、上記のケースに焦点を当て、Vuex の関連知識について読者に伝えるために、ケースを段階的に完成させます。

3.2 状態

State は、Vuex で唯一のパブリック データ ソースを提供します。すべての共有データは、State of the Store に保存されることに同意する必要があります。

初期構成では、Store オブジェクトの State プロパティを構成しました。次に、共有する必要があるデータ数を状態に入れます。
ここに画像の説明を挿入
Vuex の 1 つの機能は次のとおりです。共有. これで、データを状態に入れ、共有できるようになりました。コンポーネントは State にアクセスすることで State の内部データにアクセスできます。

this.$store.state.全局数据名称

Jiafa コンポーネントでのアクセス:
ここに画像の説明を挿入
効果は次のとおりです。
ここに画像の説明を挿入
上記により、パブリック データにアクセスするコンポーネントが正常に実装されました。テンプレート構文では、$store.state.count を使用するだけです。しかし、あちこちにこのように書くと、コードが複雑になり、Vue のコード仕様に準拠しなくなります。そこで、mapState という新しい方法が登場しました。

3.2.1 mapState 関数

mapState は vuex の関数であり、状態からデータを取得するためのコードを簡素化できます。

この関数を使用する前に導入する必要があります。コンポーネントは単純化を使用しているため、コンポーネントにそれを導入する必要があります。加算コンポーネントでカウントを取得するために最初のメソッドを使用したので、減算コンポーネントで 2 番目のメソッドを試します。

最初のステップは、mapState 関数を導入することです。2
ここに画像の説明を挿入
番目のステップは、mapState 関数を使用することです。
mapState 関数はコードの量を単純化することができ、その本質は実際には計算されたプロパティ、したがって、この関数の使用は計算されたプロパティに配置する必要があり、単純化する必要があるデータは mapState 関数に直接配置できます。ここで、3 つのポイント、展開演算子を追加する必要があります。これは、内部のデータを現在のコンポーネントの計算されたプロパティにマップすることを意味します。
ここに画像の説明を挿入
これをすべて行った後、カウントを補間構文に投入するだけです。
ここに画像の説明を挿入
効果は次のとおりです。
ここに画像の説明を挿入

3.3 突然変異

3.3.1 突然変異につながる足し算と引き算を達成する間違った方法

これまで、状態からデータを取得する 2 つの方法を見てきました。データが取得されたので、データを操作することもできます。たとえば、カウントの自己インクリメントを実現し、取得したデータに基づいてクリック イベントを直接設定したいと考えています。ただし、
ここに画像の説明を挿入
== Vuex では、コンポーネントはストア内のデータを直接変更することはできません。== したがって、この方法は非常に違法です。では、データをどのように操作すればよいでしょうか。これは、以下で紹介する必要があるものです。

3.3.2 ミューテーションの使用

ミューテーションは、ストア内のデータを変更するために使用されます。

Vuex では、Store 内のデータはミューテーションによってのみ変更でき、Store 内のデータを直接操作することはできません。

そして、このように操作するのは少し面倒ですが、== はデータの変更を集中的に監視できます。以前の誤った書き込み方法を使用して毎回データを変更すると、後でデータを維持するのに役立ちません。

以上がMutationの役割と、Mutationが使われる理由です。

以下では、Mutation を使用してデータを変更する方法を紹介します。

Store 構成ファイルでは、最初に Mutation を構成し、その中の操作データに関連する関数を構成する必要があります。
ここに画像の説明を挿入
次に、コンポーネントでミューテーションをトリガーする必要があります. トリガー方法は非常に単純で、 commit 関数を使用します. commit 関数を使用して、ミューテーションでメソッドを呼び出します。

this.$store.commit('add')

ここに画像の説明を挿入
これで、コンポーネントは加算を通常どおり使用できます。
ここに画像の説明を挿入

3.3.3 ミューテーション受け渡しパラメータ

今気づいたのは、カウントが自動的に増加するようにすることです。しかし、新しい要件を提供するために、カウントが自然に増加するかどうか確信が持てません。カウントに 5 を追加したいと考えています。この場合、パラメーターを渡して、Mutation にカウントに追加する量を伝える必要があります。

したがって、このセクションの内容は、Mutation を使用するときにパラメーターを渡す方法を読者に伝えることです。

まず、ミューテーションはまだ構成されています。

ここに画像の説明を挿入
次に、ボタン バインド イベントのミューテーションをトリガーします。
ここに画像の説明を挿入
次に、commit を使用してミューテーションをトリガーします。
ここに画像の説明を挿入
コンポーネントでの使用は、一般的な関数でパラメーターを渡す方法と実際には似ています。

3.3.4 mapMutation

状態を学習した後、mapState を学習し、面倒なデータ取得コードの問題を解決することに成功しました。今度は、同じ目的で mapMutations を学習し、コードをより簡潔で一目でわかるようにします。

それでは、減算関数を実装しましょう

最初のステップは引き続きミューテーションを構成することです。
ここに画像の説明を挿入
次に、コンポーネントで sub を使用する必要があります。最初にボタンをイベントにバインドします。
ここに画像の説明を挿入
次に、mapMutations を導入する必要があります。
ここに画像の説明を挿入
次に、mapMutations を呼び出します。前の原則と同様に、エキスパンダーを作成し、その内部サブ関数を呼び出す必要があります。
ここに画像の説明を挿入
ここで注意してください...mapMutations は、計算されたプロパティではなく、メソッドに配置する必要があります。サブハンドルがそれを使用する必要があるためです。

次に、同様の方法を使用してパラメーターの受け渡しを実装します。

最初にミューテーションで構成されます:
ここに画像の説明を挿入
次に、ボタンをイベントにバインドします:
ここに画像の説明を挿入
最後に呼び出します:
ここに画像の説明を挿入

3.4 アドバンス版デモ

上記では、カウントの基本操作を実装しました。つまり、カウントを読み取り、カウントで加算および減算演算を実行します。

ここで、要求の高度なバージョンを提示します。ボタンをクリックする場合は、1 秒待ってからカウント値に 1 を追加します。

ここでタイマーが必要であることは明らかであり、タイマーは非同期タスクとしてカウントされます。

読者はミューテーションの機能にタイマーを追加してみることができます。しかし、最終的にはページが変更されますが、Vue のブラウザー デバッガーでカウントの変更を観察する方法はありません。

非同期操作はミューテーションでは実行できず、vuex はそれらを正常に認識できません。

非同期操作を行いたい場合はどうすればよいでしょうか? 以降のコンテンツでは、この問題に焦点を当てます。

3.5 アクション

Vuex では、Action を使用して非同期タスクを処理します。

非同期操作でデータを変更する場合は、Mutation の代わりに Action を渡す必要があります。ただし、アクションでは、Mutation をトリガーして間接的にデータを変更する必要があります。

3.5.1 アクションの使用

まず、アクションはまだストアファイルに設定されています. 内部に関数があり、その関数の中にタイマーが書かれています. アクションでは、コミットを介してミューテーションで関数を呼び出す必要があるため、addAsync にパラメータを与えます.そして、このパラメーターが commit を呼び出すようにします。ここで、データはアクションで変更できないことに注意してください。ミューテーションで定義された関数のみがデータを変更する権利を持っています。

ここに画像の説明を挿入

ここでアクションを定義したので、コンポーネントでそれを使用する必要があります。

まず、イベントをボタンにバインドします。
ここに画像の説明を挿入
次に、addasync でタイマーをトリガーするには、Actionin をトリガーする必要があります。ミューテーションで関数をトリガーするにはコミットを使用する必要があり、アクションをトリガーするにはディスパッチを使用する必要があることを以前に学びました。
ここに画像の説明を挿入

3.5.2 アクション使用時のパラメータの持ち方

先ほど addAsync 関数を書いたとき、commit を呼び出して内部で add を操作しました。ここで達成したいことは、addasync に 5 を追加することです。前の説明に関連して、ここでアクションを使用する場合、パラメーターを運ぶ必要があり、追加する前にまだ 1 秒遅れていることを痛感することができます。

まず第一に、まだアクションを書いています。ここで、先ほど書いた addfive 関数を呼び出します。
ここに画像の説明を挿入

次に、コンポーネントで使用され、ボタンを設定し、イベントをボタンにバインドします。

ここに画像の説明を挿入

次に、イベント addasyncfive を記述します。
ここに画像の説明を挿入
最終的に、通常どおり使用できます。

3.5.3 mapAction

前のものと同様に、mapActions はアクションをトリガーする 2 番目の方法です。

今回は減算に1秒遅れてcountを5減算する演算を実装します。

最初のステップは、引き続きアクションを構成することです

ここに画像の説明を挿入

次に、コンポーネントで使用します。最初に mapActions 関数を導入し、それを使用してメソッドで宣言します。エキスパンダーを忘れないでください。次に、ボタンを設定し、ボタンのバインディング イベントを記述します
ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

3.6 ゲッター

Getter は、ストア内のデータを処理して新しいデータを形成するために使用されます。これは、Vue の計算されたプロパティに似ています。

Store データが変われば、Getter データも変わります。

ただし、Getter は State のデータを変更せず、ラッパーとしてのみ機能します。

したがって、このセクションでは、vuex の最後のコア概念である Getter について説明します。

3.6.1 ゲッターの使用

1 つ目は、Getter の構成です。

ゲッターはここで定義されます:
ここに画像の説明を挿入
次に、ゲッターを使用する方法が 2 つあります。最初の方法は次のとおりです。

this.$store.getters.名称

アプリで使用:
ここに画像の説明を挿入
正常に表示できます:
ここに画像の説明を挿入

3.6.2 mapGetter

それはまだ最初に導入され
ここに画像の説明を挿入
、計算されたプロパティに配置されます:
ここに画像の説明を挿入
最後に使用できます:
ここに画像の説明を挿入
効果は同じままです:
ここに画像の説明を挿入

4番目に、コード部分

main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store/index'

Vue.config.productionTip = false

new Vue({
    
    
  render: h => h(App),
  store
}).$mount('#app')

app.vue

<template>
  <div>
    <Jiafa></Jiafa>
    <Jianfa></Jianfa>
    <!-- {
    
    {
    
     $store.getters.showNum }} -->
    {
    
    {
    
     showNum }}
  </div>
</template>

<script>
import Jiafa from '@/components/Jiafa.vue'
import Jianfa from '@/components/Jianfa.vue'
import {
    
     mapGetters } from 'vuex';
export default {
    
    
  name: 'App',
  components: {
    
    Jiafa, Jianfa},
  computed: {
    
    
    ...mapGetters(['showNum'])
  },
}
</script>

<style>

</style>

store-index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

export default new Vuex.Store({
    
    
    state: {
    
    
        count: 0
    },
    mutations: {
    
    
        add(state) {
    
    
            //加加
            state.count++
        },
        addfive(state, i) {
    
    
            // 加五
            state.count += i;
        },
        sub(state) {
    
    
            //减减
            state.count--
        },
        subfive(state, i) {
    
    
            // 减五
            state.count -= i
        }
    },
    actions: {
    
    
        addAsync(context) {
    
    
            setTimeout(() => {
    
    
                context.commit('add')
            }, 1000)
        },
        addAsyncfive(context, i) {
    
    
            setTimeout(() => {
    
    
                context.commit('addfive', i)
            }, 1000)
        },
        // 减减延迟1s
        subAsync(context) {
    
    
            setTimeout(() => {
    
    
                context.commit('sub')
            }, 1000)
        },
        // 减5延迟1秒
        subAsyncfive(context, i) {
    
    
            setTimeout(() => {
    
    
                context.commit('subfive', i)
            }, 1000)
        },
    },
    getters: {
    
    
        showNum(state) {
    
    
            return '当前最新的数量是['+ state.count + ']';
        }
    }
})

ジアファ

<template>
    <div>
        <div>当前最新的count的值为:{
    
    {
    
     $store.state.count }}</div>
        <button @click="add">+1</button>
        <button @click="addfive()">+5</button>
        <button @click="addasync">延迟一秒后+1</button>
        <button @click="addasyncfive(5)">延迟一秒后加五</button>
    </div>
</template>

<script>
export default {
    
    
    name: 'Jiafa',
    methods: {
    
    
        add() {
    
    
            this.$store.dispatch('addAsync')
            this.$store.commit('add')
        },
        addfive() {
    
    
            this.$store.commit('addfive', 5)
        },
        // 延迟一秒后再加
        addasync() {
    
    
            this.$store.dispatch('addAsync')
        },
        addasyncfive(i) {
    
    
            this.$store.dispatch('addAsyncfive', i)
        }
    }
}
</script>

<style></style>

ジャンファ

<template>
    <div>
        <div>当前最新的count的值为:{
    
    {
    
     count }}</div>
        <button @click="subhandle">-1</button>
        <button @click="subi(5)">-5</button>
        <button @click="subasync">延迟一秒减一</button>
        <button @click="subasyncfive(5)">延迟一秒减5</button>
    </div>
</template>

<script>
// 引入mapState
import {
    
    mapMutations, mapState, mapActions} from 'vuex'
export default {
    
    
    name: 'Jianfa',
    computed: {
    
    
        ...mapState(['count']),
    },
    methods: {
    
    
        ...mapMutations(['sub', 'subfive']),
        ...mapActions(['subAsyncfive', 'subAsync']),
        subhandle() {
    
    
            this.sub()
        },
        subi(i) {
    
    
            this.subfive(i)
        },
        //延迟1s减一
        subasync() {
    
    
            this.subAsync()
        },
        subasyncfive(i) {
    
    
            // 延迟1s减5
            this.subAsyncfive(i)
        }
    }                                                                     
}
</script>

<style></style>

あとがき

以上が Vuex のコアコンセプトと基本的な使い方です。これが読者に役立つことを願っています!質問がある場合は、コメント欄にコメントしてください。

注意を払うことを歓迎します。フォローアップは、よりエキサイティングなコンテンツをもたらします!

おすすめ

転載: blog.csdn.net/zxdznyy/article/details/128899867