ホームページ  >  記事  >  ウェブフロントエンド  >  vuex の実装原則について詳しく見る

vuex の実装原則について詳しく見る

青灯夜游
青灯夜游転載
2023-03-20 18:14:082235ブラウズ

面接でvuexの実装原理について聞かれたら、どう答えますか? vuex の実装原理については以下の記事で詳しく解説していますので、お役に立てれば幸いです。

vuex の実装原則について詳しく見る

vuex の詳細については説明しません。簡単に復習しましょう: アプリケーションが 複数のコンポーネントの共有状態 に遭遇したとき、単に 一方向のデータ フロー は簡単に壊れます。まず、複数のビューが同じ状態に依存します。次に、異なるビューからのアクションには同じ状態への変更が必要です。前者がパラメーターを渡すことによって解決される場合、多層のネストされたコンポーネントおよび兄弟コンポーネントには適していません。後者が、親子コンポーネントからの直接参照またはイベント変更と同期状態の複数のコピーを使用することによって解決される場合、適切ではありません。コードのメンテナンスに役立ちます。

したがって、最良の方法は、コンポーネントの共有状態を抽出し、グローバル シングルトン モードで管理することです。これが vuex の基本的な考え方です。

vuex の実装原則について詳しく見る

[関連する推奨事項: vuejs ビデオ チュートリアルWeb フロントエンド開発]

つまり、 vuex の一般的な考え方 フレームワークは次のとおりです:

class Store {
    constructor() {
        // state
        // getters  
        // mutations
        // actions
    }
    // commit
    // dipatch
}

次に、書いて読むだけです。

1. vue プロジェクトの作成

vue create vue2-vuex//创建vue2项目

yarn add vuex@next --save//安装vuex

yarn serve//启动项目

2. 実装原則

1. 状態

#(1)

//store.js
// 仓库
import Vue from 'vue'
import Vuex from 'vuex'
import extra from './extra.js'

Vue.use(Vuex) //引入vuex的方式,说明Store需要install方法
export default new Vuex.Store({
    // 仓库数据源
    state: {
        count: 1,
        dowhat: 'addCount'
    },
}
//app.vue
<template>
    <div class="testState">
        <p>{{mycount}}</p>
        <p>{{dowhat}}:{{count}}</p>
    </div>
</template>

<script>
export default {
    import {
        mapState
    } from &#39;vuex&#39;
    // 推荐方式
    computed: mapState()({
        mycount: state => state.count
    }),
    // 推荐方式的简写方式
    computed: {
        // 解构的是getters
        ...mapState([&#39;count&#39;, &#39;dowhat&#39;])
    },
  }
</script>

##(2) を使用します。

##Vuex の状態ストレージは応答性があるため、ストアから取得します。インスタンスの状態を読み取る方法は、 計算プロパティ

で特定の状態を返すことです。このパターン

により、コンポーネントはグローバル状態シングルトン に依存します。モジュラー ビルド システムでは、状態を使用する必要がある各コンポーネントを頻繁にインポートする必要があり、コンポーネントのテスト時に状態をシミュレートする必要があります。Vuex は、ルートから状態を「注入」するメカニズムを提供します。コンポーネントを各サブコンポーネントに追加します (Vue.use(Vuex)

を呼び出す必要があります)

(3) 実装

したがって、

Store の 5 つの内部属性に加えて、プラグインの install

メソッドも考慮する必要があるため、一般的なフレームワークは次のようになります。これは具体的に実装できます。

class Store {
    constructor() {
        // state
        // getters  
        // mutations
        // actions
        //modules
    }
    // commit
    // dipatch
}
let Vuex = {
    Store,
    Install
}
export default Vuex
ただし、上記の状態実装には欠点があります。データが変更されたときに、state のデータを動的にレンダリングすることができません。では、state

のデータをどのようにレスポンシブにするかが重要な問題となるでしょうか?実際、

vue

data と同様に、この方法で応答性を高めることもできます。次に、install メソッドから Vue を渡す必要があるため、変更後は次のようになります:

class Store {
    constructor(options) {
        // state
        this.state = options.state
    }
}
let install = function(_Vue) {
    _Vue.mixin({
        beforeCreate() { //在组件创建之前自动调用,每个组件都有这个钩子
            if (this.$options && this.$options.store) { //this.$options读取根组件
                this.$store = this.$options.store
            } else {
                this.$store = this.$parent && this.$parent.$store
            }
        }
    })
}
2, getters

## (1)

let Vue=null
class Store {
    constructor(options) {
        // state
        this.vm = new _Vue({
          data: {
            state: options.state//data中的数据才是响应式
          }
        })
    }
      get state() {
        return this.vm.state
    }
}
let install = function(_Vue) {//用于Vue.use(plugin)
    Vue=_Vue
    _Vue.mixin({
        onBeforeCreate() { //在组件创建之前自动调用,每个组件都有这个钩子
            if (this.$options && this.$options.store) { //this.$options读取根组件
                this.$store = this.$options.store
            } else {
                this.$store = this.$parent && this.$parent.$store
            }
        }
    })
}
を使用します (2)

場合によっては状態から導出する必要があることに注意してくださいストア内 一部の状態 (追加、削除、フィルタリングなど) については、Vuex を使用してストア内で「ゲッター」を定義できます (ストアの計算されたプロパティと考えることができます)。計算されたプロパティと同様に、ゲッターの戻り値は依存関係に従ってキャッシュされ、依存関係の値が変更された場合にのみ再計算されます。ゲッターは状態を最初のパラメーターとして受け入れ、ゲッターはメソッドを通じてアクセスされます。呼び出しは結果をキャッシュせずに毎回行われます

(3) 実装

//store.js
export default new Vuex.Store({
    // 计算属性
    getters: {
        // 这里的函数不需要调用,可以直接使用,官方默认前面有get
        getCount(state) {//接受 state 作为其第一个参数
            return state.count * 100;
        }
    },
}

3、変異

(1)

 // getters
    let getters = options.getters || {}
    this.getters = {}
    Object.keys(getters).forEach(getterName => {
      Object.defineProperty(this.getters, getterName, {
        get: () => {
          return getters[getterName](this.state)
        }
      })
    })
//store.js
export default new Vuex.Store({
        // 相当于methods
    mutations: {
        // mutations内部的函数,天生具备一个形参
        add(state, n) {
            state.count += n;
        },
        decrease(state, n) {
            state.count -= n;
        }
    },
}
を使用します (2)

が Vuex ストアの状態を変更する唯一の方法であることに注意してくださいその方法は、突然変異を提出することです。 Vuex のミューテーションはイベントに似ています。各ミューテーションには、文字列 イベント タイプ (タイプ)

コールバック関数 (ハンドラー)

があります。このコールバック関数は状態の変更が行われる場所であり、最初のパラメーターとして状態を受け取りますが、突然変異ハンドラーを直接呼び出すことはできません。このオプションはイベント登録に似ています: 「タイプ increment の突然変異がトリガーされたとき、この関数を呼び出します。」 突然変異ハンドラーを起動するには、次のオプションを指定して

store.commit# を呼び出す必要があります。 ## メソッド

は、突然変異 ペイロードである store.commit に追加パラメータを渡すことができます。ほとんどの場合、ペイロードはオブジェクト。複数のフィールドを含めることができ、記録された変異が読みやすくなります。(3) 実装

methods: {
            submit() {
                console.log(&#39;success&#39;);
            },

            // 解构仓库mutations里面的方法,要啥解构啥
            ...mapMutations([&#39;add&#39;, &#39;decrease&#39;]),
            // this.$store.commit(&#39;add&#39;),
                
            ...mapActions([&#39;addAction&#39;, &#39;decreaseAction&#39;]),
            // this.addAction()调用actions里面的方法
            // this.$store.dispatch(&#39;add&#39;),
}
4、アクション

(1)

   // mutations
    let mutations = options.mutations || {}
    this.mutations = {}
    Object.keys(mutations).forEach(mutationName => {
      this.mutations[mutationName] = (arg) => {//保证多个(第二个)参数的传入
        mutations[mutationName](this.state, arg)
      }
    })
    
    commit = (method, arg) => {//使用箭头函数改变被调用的this的指向
        // console.log(this);
        this.mutations[method](arg)
  }
を使用します (2) 注

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作
  • Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
  • Action 通过 store.dispatch 方法触发
  • Action 通常是异步的,store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise
  • 一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行

(3)实现

    // actions
    let actions = options.actions || {}
    this.actions = {}
    Object.keys(actions).forEach(actionName => {
      this.actions[actionName] = (arg) => {
        actions[actionName](this, arg)
      }
    })
    
   dispatch=(method, arg) =>{
    this.actions[method](arg)
  }

5、modules

(1)使用

    // actions
    let actions = options.actions || {}
    this.actions = {}
    Object.keys(actions).forEach(actionName => {
      this.actions[actionName] = (arg) => {
        actions[actionName](this, arg)
      }
    })
    
   dispatch=(method, arg) =>{
    this.actions[method](arg)
  }
    //store.js
    modules: {
        extra: extra
    }

(2)注意

  • 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿,Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
  • 对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象
  • 对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState
  • 对于模块内部的 getter,根节点状态(rootState)会作为第三个参数暴露出来

三、整体代码

let Vue = null//全局的_Vue

class Store {
  constructor (options) {
    // state
    //this.state = options.state 写法不完美,当改变数据的时候,不能动态的渲染,所以需要把data中的数据做成响应式的
    this.vm = new _Vue({
      data: {
        state: options.state//data中的数据才是响应式
      }
    })

    // getters
    let getters = options.getters || {}
    this.getters = {}
    Object.keys(getters).forEach(getterName => {
      Object.defineProperty(this.getters, getterName, {
        get: () => {
          return getters[getterName](this.state)
        }
      })
    })

    // mutations
    let mutations = options.mutations || {}
    this.mutations = {}
    Object.keys(mutations).forEach(mutationName => {
      this.mutations[mutationName] = (arg) => {//保证多个(第二个)参数的传入
        mutations[mutationName](this.state, arg)
      }
    })

    // actions
    let actions = options.actions || {}
    this.actions = {}
    Object.keys(actions).forEach(actionName => {
      this.actions[actionName] = (arg) => {
        actions[actionName](this, arg)
      }
    })

  }

  dispatch=(method, arg) =>{
    this.actions[method](arg)
  }

  commit = (method, arg) => {
    // console.log(this);
    this.mutations[method](arg)
  }

  get state() {
    return this.vm.state
  }

}

let install = function(_Vue) {
  Vue = _Vue
  Vue.mixin({
    beforeCreate() {//在组件创建之前自动调用,每个组件都有这个钩子
      if (this.$options && this.$options.store) {  // this.$options读取到根组件
        this.$store = this.$options.store
      } else { // //如果不是根组件的话,也把$store挂到上面,因为是树状组件
        this.$store = this.$parent && this.$parent.$store
      }
    }
  })
}

let Vuex = {
  Store,
  install
}

export default Vuex

(学习视频分享:vuejs入门教程编程基础视频

以上がvuex の実装原則について詳しく見るの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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