vuex 使用文檔

来源:http://www.cnblogs.com/nmxs/archive/2017/04/07/6677330.html
-Advertisement-
Play Games

安裝 直接下載CDN 引用 <script src="/path/to/vue.js"></script> <script src="/path/to/vuex.js"></script> npm npm install vuex --save 在一個模塊化的打包系統中,您必須顯式地通過Vue.us ...


安裝

直接下載CDN 引用

  <script src="/path/to/vue.js"></script>

  <script src="/path/to/vuex.js"></script>

npm

  npm install vuex --save

在一個模塊化的打包系統中,您必須顯式地通過Vue.use() 來安裝Vuex

  import Vue from 'vue'

  import Vuex from 'vuex'

  Vue.use(Vuex)

 

  Vuex 是一個專為Vue.js 應用程式開發 的狀態管理模式,集中式存儲管理應用的所有組件狀態。

  狀態管理包含以下幾個部分狀態:

     state 驅動應用的數據源;

      view 以生命方式將 state 映射到視圖。

       actions  響應在view 上的用戶書輸入導致的狀態變化。

 

幫助我們管理共用狀態,中大型單頁面應用。

 

  state

    單一狀態樹 Vuex使用單一狀態樹用一個對象就包含了全部的應用層級狀態。

    在Vue 組件中獲得Vuex 狀態。

    由於Vuex的狀態存儲是響應式的,從store 實例中讀取狀態最簡單的方法

    就是在計算屬性中返回某個狀態。

    創建一個Counter 組件

    const Counter = {

        template: '<div>{{ count }}</div>'

        computed: {

          count ()

            return store.state.count

          }

        }

      }

  每次 store.state.count 變化的時候,都會重新求取計算屬性,並且觸發更

 新相關的DOM

    Vuex 通過 store 選項,提供了一種機制將狀態從根組件『註入』到每一個子組件

      中(需調用 Vue.use(Vuex)):

      const app = new Vue({

        el:'#app',

        // store 對象提供給 “store” 選項,這可以把 store 的實例註入所 有的子組件

        store,

        components: {Counter},

      template: '

        <div class="app">

          <counter></counter>

        </div>

        '

      })

 

  通過在根實例中註冊 store 選項,該store 實例會註冊入到跟組件下的所有

    子組件,且子組件能通過 this.$store 訪問到。更新 counter 的實現:

      const Counter = {

        template : '<div>{{ count }}</div>',

        computed: {

          count this.$store.state.count

          }

      }

    mapState 輔助函數

      當一個組件需要獲取多個狀態時候,將這些狀態都聲明為計算屬性會有些冗餘。

      為瞭解決這個問題,我們可以使用 mapState 輔助函數幫助我們生成計算屬性。

      // 在單獨構建的版本中輔助函數為 Vuex.mapState

      import { mapState } from 'vuex'

        export default {

          computed: mapState({

            // 箭頭函數可以使代碼更簡潔

              count: state => state.count,

            // 傳字元串參數 ‘count’ 等同於 ‘state => state.count’

              countAlias: 'count',

            // 為了能夠使用 ‘this’ 獲取局部狀態,必須使用常規函數

              countPlusLocalState(state) {

                  return state.count + this.localCount

                }

            })

         }

    當映射的計算屬性的名稱與 state 的子節點名稱相同時,我們也

        可以給 mapState 傳一個字元串數組。

          computed: mapState([

            // 映射 this.count store.state.count

            'count'

          ])

 

    組件仍然保有局部狀態。

    Getters

      有時候我們需要從store 中的state 中 的state 中派生一些狀態,列如對列表進

      行過濾並計算。

      computed: {

        doneTodosCount() {

            return this.$store.state.todos.filter(todo => todo.done).length

        }

      }

 

    Vuex 允許我們再store 中定義getters (可以認為是stroe 的計算屬性)

      Getters 接受state 作為其第一個參數。

        const store = new Vuex.Store({

            state: {

              todos:[

                {id:1, text: '...' ,done: true},

                {id:2,text:'...',done: false}

              ]

            },

          getters: {

            doneTodos: state => {

                return state.todos.filter(todo=> todo.done)

              }

            }

          })

 

    Getters 會暴露為store.getters 對象:

    store.getters.doneTodos // [{id:1,text: '...',done:true}]

 

    Getter 也可以接受其他getters 作為第二個參數:

      getters: {

          doneTodosCount: (state,getters) => {

            return getters.doneTodos.length

          }

      }

    store.getters.doneTodosCount  // -> 1

      我們可很容易的在任何組件中使用

        computed: {

          doneTodosCount() {

            return this.$store.getters.doneTodosCount

        }

      }

    mapGetters 輔助函數

    mapGetters 輔助函數僅僅是 store 中的getters 映射到局部計算屬性。

      import {mapGetter} form 'vuex'

      export default {

        computed: {

          // 使用對象展開運算符將 getters 混入

          ...mapGetters([

              ‘doneTodosCount’,

              'anotherGetter'

            ])

          }

        }

 

  如果你想講一個getter 屬性另取名字,使用對象性時

      mapGetters({

          // 映射 this.doneCount store.getters.doneTodosCount

          doneCount: 'doneTodosCount'

      })

 

    Mutations

        更改Vuex store 中的狀態的唯一方式就是提交 mutation Vuex 中的mutation

        非常類似於事件,每個 mutation 都有一個字元串的 事件類型 和回調函數。這個

        回調函數就是我們實際進行狀態更改的地方。並且他會接受 state 作為第一個參數。

    const store = new Vue.Store({

        state: {

            count: 1

        },

      mutations: {

          inctement (state) {

          state.count++

        }

      }

    })

 

  當觸發一個類型為 increment mutation 時,調用此函數。要喚醒一個

     mutation handler,你需要以相應的 type 調用 store.commit 方法

       store.commit('increment')

      提交載荷(Payload)

      你可以向store.commit 傳入額外的參數,即mutation 的載荷:

            mutations: {

          increment (state, n) {

          state.count += n

        }

      }

      store.commit('increment', 10)

   在大多數情況下,載荷應該是一個對象,這樣可以包含多個欄位並且記錄 mutation會更易讀。

      mutations: {

      increment (state,payload) {

        state.count += payload.amount

        }

      }

      store.commit('increment', {

        amount:10

    })

 

  對象風格的提交方式

    提交mutation 的另一種方式直接使用包含 type 屬性的對象:

      store.commit({

        type: 'increment',

        amount:10

      })

  當使用對象風格的提交方式,整個對象作為載荷傳給mutation 函數,因此handler保持不變:

       mutations: {

        increment (state, payload) {

          state.count += payload.amount

        }

       }

 

  Mutations 需遵守vue 的響應規則

    既然Vuexstore 中的狀態是響應式的,那麼當我們變更狀態時,監視狀態的vue更新 ,這也意味值Vue 中的mutation 也需要與使用 Vue 一樣遵守一些註意事項。

      1. 最好提前在你的store 中初始化好所有的所需要的屬性。

      2.當需要在對象上提交新屬性時,你應該使用

        Vue.set(obj, 'newProp', 123)

      使用新對象代替老對象  state.obj= {...state.obj ,newProp: 123}

      使用常量替代 Mutation 事件類型

      使用常量替代 mutation 事件類型在各種 Flux 實現中是很常見的模式

      export const SOME_MUTATION = 'SOME_MUTATION';

      import Vuex from 'vuex'

      import {SOME_MUTATION } from './mutation-types'

      const store = new Vuex.Store({

          state{...}

          mutations: {

            // 我們可以使用 ES2015 風格的計算屬性命名功能來使用一個常量作為函數名

            [SOME_MUTATION] (state) {

            //  mutate state

            }

          }

      })

 

mutation 必須是同步函數

    一條重要的原則是記住 mutation 必須是同步函數。

        mutations: {

          someMutation (state) {

            api.callAsyncMethod(() => {

                state.count++

            })

          }

        }

 

在組件中提交 Mutations

    你可以在組件中使用 this.$store.commit('xxx') 提交 mutation,或者使使用 mapMutations輔助函數將組建中的methods 映射為 store.commit 調用 (需要在根節點註入 store)

    import {mapMutations} from 'vuex'

      expor default {

        methods: {

          mapMutations([

              methods: {

                mapMutations([

                  'increment'  // 映射 this.increment() this.$store.commit('increment')

          ]),

        mapMutations({

              add: 'increment'  // 映射 this.add() this.$store.commit('increment')

          })

        }

      ])

      }

    }

 

Actions   

    在mutation 中混非同步調用會導致你的程式很難調試。

Actions

    Action 類似於 mutation,不同在於。

    Action 提交的是 mutation ,而不是直接變更狀態。

    Action 可以包含任意非同步操作。

    註冊一個簡單的 action

    const store = new Vuex.Store({

      state: {

          count0

      }

    mutations: {

      increment (state) {

        state.count++

      }

    },

    actions: {

        increment (context){

          context.commit('increment')

          }

        }

    })

 

Action 函數接受一個與store 實例具有相同方法和屬性的context 對象,因此你可以調用 context.commit 提交一個mutation,或者通過 context.state

    context.getters 來獲取 state getters 當我們在之後介紹到Modules時,

    你就知道 context 對象為什麼不是store 實例本身了。

    actions: {

      increment({commit}){

        commit('increment')

      }

    }

 

分發 Action

    Action 通過 store.dispatch 方法觸發:

     store.dispatch('increment')

    我們可以在 action 內部執行非同步操作。

    actions: {

      incrementAsync({commit}){

        setTimeout(() => {

          commit('increment')

        },1000)

        }

      }

 

  Actions 支持同樣的載荷方式和對象方式進行分發

      // 以載荷形式分發

    store.dispatch('incrementAsync',{

      amount:10

    })

    // 以對象形式分發

      store.dispatch({

        type: 'incrementAsync',

        amount:10

      })

 

在組件中分發 Action

    你在組件中使用 this.$store.dispatch('xxx') 分發 action,或者使用map Actions輔助函數將組件的methods 映射為store.dispatch 調用

    import {mapActions } from 'vuex'

      export default{

        methods:([

          'increment'  // 映射 this.increment() this.$store.dispatch('increment')

        ])

      mapActions({

          add: 'inctement'    // 映射 this.add() this.$store.dispatch('increment')

        })

      }

 

組合 Actions

    Action 通常是非同步的,那麼如何知道 action 什麼時候結束。

    你需要明白 store.dispatch 可以處理被處觸發的action 的回調函數返回的Promise

     並且 store.dispatch 仍舊返回Promise

 

    actions: {

        actionA({commit}){

        return new Promise((resolve)=>{

            setTimeout (() => {

              commit('someMutation')

              resolve()

            },1000)

          })

        }

      }

 

  現在你可以

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

        //...

      })

  在另一個 action 中也可以

    actions: {

      actionB({dispath,commit}){

        return dispatch('actionA').then(() => {  

        commit('someOtherMutation')

      })

    }

    }

  我們利用async/ await

    // 假設 getData() getOther() 返回的是一個 Promis

    actions:{

        async actionA ({commit}){

          commit('gotData',await getData())

        },

        async actionB({dispatch,commit}){

          await dispatch('actionA')  //  等待 actionA 完成

          commit('goOtherData', await getOtherData())

        }

      }

    Modules

      使用單一狀態樹,當應用變的很大的時候,store 對象會變的臃腫不堪。

      Vuex 允許我們將store 分割到模塊。每一個模塊都有自己的state, mutation,action, getters, 甚至是嵌套子模塊從上到下進行類似的分割。

 

      const moduleA = {

          state: {...},

        mutations: {...}

        actions: {...}

        getters:{...}

        }

    const moduleA = {

        state: {...},

        mutations: {...}

        actions: {...}

      }

    const store = new Vuex.Store({

      modules: {

          a:moduleA,

          b:moduleB

        }

      })

    store.state.a   // -> moduleA 的狀態

    store.state.b // -> moduleB 的狀態

模塊的局部狀態

    對於模塊內部的 mutation getter, 接收的第一個參數是模塊的局部狀態。

      const moduleA = {

          state: {count:0},

          mutations: {

            increment (state) {

                //  state 模塊的局部狀態

                state.count++

            }

          },

      getters: {

        doubleCount (state) {

        return state.count * 2

        }

      }

    }

 

  同樣對於模塊內部的action, context.state 是局部狀態,根節點的窗臺石context.rootState:

      const moduleA = {

          actions: {

          incrementIfOddOnRootSum ({state, commit ,rootState}) {

            if((state.count + rootState.count) %2 ===1){

                commit('increment')

          }

         }

        }

      }

 對於模塊內部的getter,跟節點狀態會作為第三個參數:

      const  moduleA = {

          getters: {

            getters: {

              sumWithRootCount (state,getters,rootState) {

                      return state.count + rootState.count

                }

              }

          }

        }

 

命名空間

    模塊內部的action, mutation , getter 現在仍然註冊在全局命名空間    這樣保證了多個模塊能夠響應同一 mutation action. 也可以通過添加首碼 或者 尾碼的

      方式隔離各個模塊,以免衝突。

      // 定義 getter, action , mutation 的名稱為常量,以模塊名 ‘todo’ 為首碼。

        export  const  DONE_COUNT = 'todos/DONE_COUNT'

        export  const  FETCH_ALL =  'todos/FETCH_ALL'

        export  const TOGGLE_DONE = 'todos/TOGGLE_DONE'

              import * as types form '../types'

    // 使用添加瞭解首碼的名稱定義, getter, action mutation

        const todosModule = {

        state : {todo: []},

        getters: {

          [type.DONE_COUNT]  (state) {

          }

      }

    actions: {

        [types.FETCH_ALL] (context,payload) {

       }

      },

    mutations: {

        [type.TOGGLE_DONE] (state, payload)

      }

    }

模塊動態註冊

    在store 創建之後,你可以使用 store.registerModule 方法註冊模塊。

      store.registerModule('myModule',{})

      模塊的狀態將是 store.state.myModule.

      模塊動態註冊功能可以使讓其他Vue 插件為了應用的store 附加新模塊

      以此來分割Vuex 的狀態管理。

 

    項目結構

      Vuex 並不限制你的代碼結構。但是它規定了一些需要遵守的規則:

        1.應用層級的狀態應該集中到單個store 對象中。

        2.提交 mutation 是更改狀態的唯一方法,並且這個過程是同步的。

        3.非同步邏輯應該封裝到action 裡面。

          只要你遵守以上規則,如何組織代碼隨你便。如果你的 store 文件太大,

          只需將 actionmutation、和 getters 分割到單獨的文件

          對於大型應用,我們會希望把 Vuex 相關代碼分割到模塊中。下麵是項目結構示例

 

├── index.html

├── main.js

├── api │   

  └── ... # 抽取出API請求

├── components

│   ├── App.vue

│   └── ...

└── store    

  ├── index.js     # 我們組裝模塊並導出 store 的地方    

  ├── actions.js        # 根級別的 action    

  ├── mutations.js      # 根級別的 mutation    

  └── modules       

     ├── cart.js       # 購物車模塊        

    └── products.js   # 產品模塊


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 由OpenDigg 出品的前端開源項目周報第十五期來啦。我們的前端開源周報集合了OpenDigg一周來新收錄的優質的前端開源項目,方便前端開發人員便捷的找到自己需要的項目工具等。 ...
  • 本文講解下Git的使用,包括使用Git上傳項目工程到Github,文末有彩蛋哦。 ...
  • 今天朋友去面試被問到一個問題,原型實現數組去重,乍一聽著實有點蒙,但細細想來有些靈感 數組去重並不難,定義一個空數組,遍歷要去重的數組的每一項,利用flag作為判斷空數組中是否有一樣的元素的標識,flag為true說明沒有一樣的,就添加到空數組中 利用原型實現,其實也就是在數組的原型上添加一個方法, ...
  • 這些數組的操作方法會改變原來的數組。在使用 Vue 或者 Angular 等框架的時候會非常實用,使用這些方法修改數組會觸發視圖的更新。 ...
  • 原文鏈接:http://caibaojian.com/mobile web app fix.html 寫一個好的web app初始化樣式很重要,以下為之前的flexible.js中項目的同個樣式。 ...
  • 前些天公司要求在微信移動端做上傳圖片並預覽的功能,要求能夠調用攝像頭拍照並立即預覽。 在網上搜了一些方法,開始自己寫了個簡單的功能實現代碼。結果發現移動端拍照出來的圖片動不動就2M+,又因為要批量上傳,為用戶的流量和上傳速度考慮,我決定做一下優化,看能不能在預覽前就壓縮一下圖片尺寸。 結果又是一陣百 ...
  • 1. rem為單位時,根元素html的font-size 必須>=12px,否則 預設為font-size:12px。 再另外,有許多朋友問我:為啥 html 設置成 62.5%,或者 10px 時,這種換算無效了呢?經過研究發現,不知道什麼時候開始,小於 12px 或者 75% 的字體大小 rem ...
  • HTML:超文本標記語言(HyperText Markup Language),不是一種編程語言,是標記語言 HTML元素: <p>段落</p> HTML標簽: <p>段落</p> HTML聲明:<!DOCTYPE>並不是標簽 HTML5:<!DOCTYPE html> HTML4.0.1 stri ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...