【フロントエンドvueインタビュー】vuex

Vuexとは何ですか?

Vuex は、Vue.js アプリケーション専用に開発された状態管理パターンです。集中ストレージを使用してアプリケーションのすべてのコンポーネントの状態を管理し、対応するルールを使用して状態が予測可能な方法で変化することを保証します。

vuex のフローチャート

ここに画像の説明を挿入します

Vuex と単純なグローバル オブジェクトの違い

  • Vuex の状態ストレージはリアクティブです。 Vue コンポーネントがストアから状態を読み取るときに、ストア内の状態が変化すると、それに応じて対応するコンポーネントが効率的に更新されます。
  • ストア内で状態を直接変更することはできません。ストア内の状態を変更する唯一の方法は、ミューテーションを明示的にコミットすることです。これにより、あらゆる状態変化を簡単に追跡できるようになり、アプリケーションをより深く理解するのに役立ついくつかのツールを実装できるようになります。

独自のパブリック データ ソースを提供し、すべての共有データはデータと同様にストアの状態に保存されます。

import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex)
 
export default new Vuex.Store({
    
    
  state: {
    
    
    name:"张三",
    age:12,
    count:0
  },
})

//调用
this.$store.state.count

//template中直接用
<div>{
    
    {
    
    $store.state.count}}</div>

由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态

地図の状態

コンポーネントが複数の状態を取得する必要がある場合、これらの状態を計算されたプロパティとして宣言することは、多少反復的で冗長になります。この問題を解決するには、mapState ヘルパー関数を使用して、計算されたプロパティを生成できます。

import {
    
     mapState } from "vuex";
...
computed: mapState({
    
    
      // 箭头函数可使代码更简练
      name: state => state.name,

       // 传字符串参数 'age' 等同于 `state => state.age`
      age: 'age',

      // 为了能够使用 `this` 获取局部状态,必须使用常规函数
      countPlusAge (state) {
    
    
        return state.age + this.count
      }
    })

マップされた計算属性の名前が state の子ノードの名前と同じ場合、文字列配列を mapState に渡すこともできます。

computed: mapState([
  // 映射 this.age 为 store.state.age
  'age',
   // 映射 this.name 为 store.state.name
  'name'
])
// ===等同于===
computed:  mapState({
    
    age:'age', name: 'name'})

ローカルで計算されたプロパティと混合

computed: {
    
    
  localComputed () {
    
     /* ... */ },

  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    
    
    // ...
  })
}

ゲッター

Vuex を使用すると、ストア内で「ゲッター」を定義できます (ストアの計算されたプロパティと考えることができます)。計算されたプロパティと同様に、 getter
の戻り値は依存関係に基づいてキャッシュされ、依存関係の値が変更された場合にのみ再計算されます。 Getter の使用を学習すると、state
を通じてデータを繰り返し取得することを避けることができます。

Getter は最初のパラメータとして state を受け入れます。それに応じて state 内のデータを処理し、最終的に必要なデータを返すことができます。

//vuex
getters: {
    
    
      skillList: state => {
    
    
        return state.skill.filter(item => item.type === 1)
      }
    }

//页面
computed: {
    
    
      skillList() {
    
    
        return this.$store.getters.skillList
      }
    }   
    

ゲッターは、他のゲッターを 2 番目の引数として受け入れることもできます。

getters: {
    
    
      skillList: state => {
    
    
        return state.skill.filter(item => item.type === 1)
      },
      skillCount: (state, getters) => {
    
    
        return getters.skillList.length
      },
    }

computed: {
    
    
      skillList() {
    
    
        return this.$store.getters.skillList
      },
      count() {
    
    
        return this.$store.getters.skillCount
      }
    }

ゲッターは、データを直接返すだけでなく、ゲッターに関数を返させることでパラメーターをゲッターに渡すこともできます。ストア内の配列をクエリするときに非常に便利です。

getters: {
    
    
      skillList: state => (type) => {
    
    
        return state.skill.filter(item => item.type === type)
      },
      skillCount: (state, getters) => (type) => {
    
    
        return getters.skillList(type).length
      },
    }

computed: {
    
    
      skillList() {
    
    
        return this.$store.getters.skillList(2)
      },
      count() {
    
    
        return this.$store.getters.skillCount(2)
      }
    }

mapGetters ヘルパー関数は、ストア内のゲッターをローカルで計算されたプロパティにマップするだけです。

computed: {
    
    
      ...mapGetters([
        'skillList',
        'skillCount'
      ])
    }

突然変異

Vuex ストアの状態を変更する唯一の方法は、ミューテーションを送信することです。 Vuex のミューテーションはイベントと非常に似ています。各ミューテーションには文字列イベント タイプ (タイプ) とコールバック関数 (ハンドラー) があります。このコールバック関数は、実際に状態を変更する場所であり、最初のパラメータとして状態を受け取ります。

  state: {
    
    
    count: 1
  },
  mutations: {
    
    
    increment (state) {
    
    
      // 变更状态
      state.count++
    }
  }

突然変異を引き起こす

store.commit('increment')

追加のパラメータを store.commit に渡すことができます。これは、ミューテーションのペイロードです。

mutations: {
    
    
  incrementByCount (state, n) {
    
    
    state.count = state.count + n
  }
}


store.commit('incrementByCount', 10)

ほとんどの場合、ペイロードはオブジェクトである必要があり、通常受け取るパラメーターにはペイロードという名前が付けられているため、複数のフィールドを含めることができ、記録された変異がより読みやすくなります。

// 定义 mutation
mutations: {
    
    
  incrementByCount (state, payload) {
    
    
    state.count = state.count  + payload.count
  }
}
// 触发 mutation
store.commit('incrementByCount', {
    
    
  count: 10
})

オブジェクトスタイルの送信

store.commit({
    
    
  type: 'incrementByCount',
  count: 10
})

マップの突然変異

mapMutation は配列形式でパラメータを受け取ります

...mapMutations([
  // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
  'increment'
]),

mapMutation はオブジェクト形式でパラメータを受け取ります

...mapMutations({
    
    
  [别名]: [Mutation type] 
})
...mapMutations({
    
    
  add: 'increment'
})

アクション

Action Mutation と似ていますが、次の点が異なります。

  • アクションは、状態を直接変更するのではなく、突然変異を送信します。
  • アクションには、任意の非同期操作を含めることができます。 vuex の使用中に、複数のミューテーションを 1 つのアクションにマージしたり、アクションを通じて非同期操作を実行したりできます。

基本的な使い方

Action 関数は、ストア インスタンスと同じメソッドとプロパティを持つコンテキスト オブジェクトを受け入れるため、context.commit を呼び出して変更をコミットしたり、context.state と context.getters を通じて状態とゲッターを取得したりできます。

  state: {
    
    
    count: 1
  },
  mutations: {
    
    
    increment (state) {
    
    
      state.count++
    }
  },
  actions: {
    
    
    // 同步 action
    increment (context) {
    
    
      context.commit('increment')
    },
    // 异步 action
    incrementAsync (context) {
    
    
      setTimeout(() => {
    
    
        context.commit('increment')
      }, 1000)
    }
  }

実際には、コードを簡素化するために ES2015 パラメーターの構造化をよく使用します (特に commit を何度も呼び出す必要がある場合)。

actions: {
    
    
  increment ({
     
      commit }) {
    
    
    commit('increment')
  }
}

急送

アクションは、store.dispatch メソッドを通じてアクションをディスパッチします。

store.dispatch('increment')

ペイロードを送信する

アクションのペイロードである追加パラメータを store.dispatch に渡すことができます。

action: {
    
    
  increment ({
     
     commit}, payload) {
    
    
    // 具体 action 内容
  }
}


store.dispatch('increment', {
    
    count: 10})

//对象风格的提交方式
store.dispatch({
    
    
  type: 'increment',
  count: 10
})


マップアクション

mapActions ヘルパー関数は、送信されたアクションの記述を簡素化するのに役立ちます。

//mapActions 接收数组格式的参数
...mapActions([
  // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
  'increment'
]),


//mapActions 接收对象格式的参数
//在某些情况,我们需要对 Action 中的函数名重命名以避免和组件内部的变量冲突,这时候我们可以使用对象的方式接收参数:
...mapActions({
    
    
  [别名]: [Action name] 
})
// 例:将 `this.add()` 映射为 `this.$store.dispatch('increment')`
...mapActions({
    
    
  add: 'increment'
})

コンビネーションアクション

アクションは通常、非同期です。場合によっては、アクションがいつ終了するかを知り、終了後に対応する他の操作を実行する必要があります。さらに重要なのは、複数のアクションを組み合わせて、より複雑な非同期プロセスを処理できることです。
まず、store.dispatch はトリガーされたアクションのハンドラー関数によって返される Promise を処理でき、store.dispatch は依然として Promise を返すことを理解する必要があります。

actions: {
    
    
  actionA ({
     
      commit }) {
    
    
    return new Promise((resolve, reject) => {
    
    
      setTimeout(() => {
    
    
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

これで、次のことが可能になります。

store.dispatch('actionA').then(() => {
    
    
  // ...
})

別のアクションでも実行できます。

actions: {
    
    
  // ...
  actionB ({
     
      dispatch, commit }) {
    
    
    return dispatch('actionA').then(() => {
    
    
      commit('someOtherMutation')
    })
  }
}

最後に、async /await を利用すると、次のようにアクションを作成できます。

// 假设 getData() 和 getOtherData() 返回的是 Promise
actions: {
    
    
  async actionA ({
     
      commit }) {
    
    
    commit('increment', await getData())
  },
  async actionB ({
     
      dispatch, commit }) {
    
    
    await dispatch('actionA') // 等待 actionA 完成
    commit('increment', await getOtherData())
  }
}

モジュール

大規模なプロジェクトに遭遇すると、データ量が多くなり、ストアが非常に肥大化します。

上記の問題を解決するために、Vuex ではストアをモジュールに分割することができます。各モジュールには、独自の状態、突然変異、アクション、ゲッター、さらにはネストされたサブモジュールがあります。

const moduleA = {
    
    
  state: {
    
     ... },
  mutations: {
    
     ... },
  actions: {
    
     ... },
  getters: {
    
     ... }
}

const moduleB = {
    
    
  state: {
    
     ... },
  mutations: {
    
     ... },
  actions: {
    
     ... }
}

const store = new Vuex.Store({
    
    
  modules: {
    
    
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态


おすすめ

転載: blog.csdn.net/qq_37215621/article/details/133963062