Przeglądaj źródła

[Feature] middlewares to ignore 'silent' mutation && fixed FSB mutations (#137)

- Added support for 'silent' flag
- Fixed FSB standards https://github.com/acdlite/flux-standard-action
- Updated tests
- Updated docs
- Updated API doc to include 'object style mutation'
Blake Newman 9 lat temu
rodzic
commit
cbfd5b8ade
4 zmienionych plików z 94 dodań i 6 usunięć
  1. 14 1
      docs/en/api.md
  2. 31 0
      docs/en/mutations.md
  3. 4 2
      src/index.js
  4. 45 3
      test/unit/test.js

+ 14 - 1
docs/en/api.md

@@ -79,10 +79,23 @@ const store = new Vuex.Store({ ...options })
 
 ### Vuex.Store Instance Methods
 
-- **dispatch(mutationName: String, ...args)**
+- **dispatch(mutationName: String, ...args) | dispatch(mutation: Object)**
 
   Directly dispatch a mutation. This is useful in certain situations are in general you should prefer using actions in application code.
 
+  *Object-Style Dispatch*
+
+  > requires >=0.6.2
+
+  You can also dispatch mutations using objects:
+
+  ``` js
+  store.dispatch({
+    type: 'INCREMENT',
+    payload: 10
+  })
+  ```
+
 - **watch(pathOrGetter: String|Function, cb: Function, [options: Object])**
 
   Watch a path or a getter function's value, and call the callback when the value changes. Accepts an optional options object that takes the same options as Vue's `vm.$watch` method.

+ 31 - 0
docs/en/mutations.md

@@ -67,6 +67,37 @@ mutations: {
 }
 ```
 
+### Silent Dispatch
+
+> requires >=0.7.0
+
+In some scenarios you may not want the middlewares to record the state change. Multiple dispatches to the store in a short period or polled do not always need to be tracked. In these situations is may be considered appropriate to silent the mutations. 
+
+*Note:* This should be avoided where necessary. Silent mutations break the contract of all state changes being tracked by the devtool. Use sparingly and where absolutely necessary.
+
+Dispatching without hitting middlewares can be achieved with a `silent` flag.
+
+``` js
+/**
+ * Example: Progress action.
+ * Dispatches often for changes that are not necessary to be tracked
+ **/
+export function start(store, options = {}) {
+  let timer = setInterval(() => {
+    store.dispatch({
+      type: INCREMENT,
+      silent: true,
+      payload: {
+        amount: 1,
+      },
+    });
+    if (store.state.progress === 100) {
+      clearInterval(timer);
+    }
+  }, 10);
+}
+```
+
 ### Mutations Follow Vue's Reactivity Rules
 
 Since a Vuex store's state is made reactive by Vue, when we mutate the state, Vue components observing the state will update automatically. This also means Vuex mutations are subject to the same reactivity caveats when working with plain Vue:

+ 4 - 2
src/index.js

@@ -77,9 +77,11 @@ class Store {
    */
 
   dispatch (type, ...payload) {
+    let silent = false
     // compatibility for object actions, e.g. FSA
     if (typeof type === 'object' && type.type && arguments.length === 1) {
-      payload = [type]
+      payload = [type.payload]
+      if (type.silent) silent = true
       type = type.type
     }
     const mutation = this._mutations[type]
@@ -93,7 +95,7 @@ class Store {
         mutation(state, ...payload)
       }
       this._dispatching = false
-      this._applyMiddlewares(type, payload)
+      if (!silent) this._applyMiddlewares(type, payload)
     } else {
       console.warn(`[vuex] Unknown mutation: ${type}`)
     }

+ 45 - 3
test/unit/test.js

@@ -249,6 +249,48 @@ describe('Vuex', () => {
     expect(mutations[0].nextState.a).to.equal(3)
   })
 
+  it('middleware should ignore silent mutations', function () {
+    let initState
+    const mutations = []
+    const store = new Vuex.Store({
+      state: {
+        a: 1
+      },
+      mutations: {
+        [TEST] (state, n) {
+          state.a += n
+        }
+      },
+      middlewares: [
+        {
+          onInit (state) {
+            initState = state
+          },
+          onMutation (mut, state) {
+            expect(state).to.equal(store.state)
+            mutations.push(mut)
+          }
+        }
+      ]
+    })
+    expect(initState).to.equal(store.state)
+    store.dispatch(TEST, 1)
+    store.dispatch({
+      type: TEST,
+      payload: 2
+    })
+    store.dispatch({
+      type: TEST,
+      silent: true,
+      payload: 3
+    })
+    expect(mutations.length).to.equal(2)
+    expect(mutations[0].type).to.equal(TEST)
+    expect(mutations[1].type).to.equal(TEST)
+    expect(mutations[0].payload[0]).to.equal(1)
+    expect(mutations[1].payload[0]).to.equal(2)
+  })
+
   it('watch', function (done) {
     const store = new Vuex.Store({
       state: {
@@ -396,14 +438,14 @@ describe('Vuex', () => {
         a: 1
       },
       mutations: {
-        [TEST] (state, action) {
-          state.a += action.by
+        [TEST] (state, amount) {
+          state.a += amount
         }
       }
     })
     store.dispatch({
       type: TEST,
-      by: 2
+      payload: 2
     })
     expect(store.state.a).to.equal(3)
   })