소스 검색

middleware overhaul

Evan You 9 년 전
부모
커밋
c18f5ef33a
2개의 변경된 파일46개의 추가작업 그리고 6개의 파일을 삭제
  1. 7 3
      examples/todomvc/vuex/middlewares.js
  2. 39 3
      src/index.js

+ 7 - 3
examples/todomvc/vuex/middlewares.js

@@ -1,5 +1,9 @@
 import { STORAGE_KEY } from './index'
 
-export default [function (mutation, { todos }) {
-  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
-}]
+const localStorageMiddleware = {
+  onMutation (mutation, { todos }) {
+    localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
+  }
+}
+
+export default [localStorageMiddleware]

+ 39 - 3
src/index.js

@@ -41,6 +41,16 @@ export default class Vuex {
 
     // middlewares
     this._middlewares = middlewares
+    this._needSnapshots = middlewares.some(m => m.snapshot)
+    const initialSnapshot = this._prevSnapshot = this._needSnapshots
+      ? deepClone(state)
+      : null
+    // call init hooks
+    middlewares.forEach(m => {
+      if (m.onInit) {
+        m.onInit(m.snapshot ? initialSnapshot : state)
+      }
+    })
   }
 
   /**
@@ -64,16 +74,26 @@ export default class Vuex {
 
   dispatch (type, ...payload) {
     const mutation = this._mutations[type]
+    const prevSnapshot = this._prevSnapshot
     const state = this.state
+    let snapshot
     if (mutation) {
+      // apply the mutation
       if (Array.isArray(mutation)) {
         mutation.forEach(m => m(state, ...payload))
       } else {
         mutation(state, ...payload)
       }
-      // middleware after hooks
-      this._middlewares.forEach(middleware => {
-        middleware({ type, payload }, state)
+      // invoke middlewares
+      if (this._needSnapshots) {
+        snapshot = this._prevSnapshot = deepClone(state)
+      }
+      this._middlewares.forEach(m => {
+        if (m.snapshot) {
+          m.onMutation({ type, payload }, snapshot, prevSnapshot)
+        } else {
+          m.onMutation({ type, payload }, state)
+        }
       })
     } else {
       console.warn(`[vuex] Unknown mutation: ${ type }`)
@@ -156,3 +176,19 @@ function mergeObjects (arr, allowDuplicate) {
     return prev
   }, {})
 }
+
+function deepClone (obj) {
+  if (Array.isArray(obj)) {
+    return obj.map(deepClone)
+  } else if (obj && typeof obj === 'object') {
+    var cloned = {}
+    var keys = Object.keys(obj)
+    for (var i = 0, l = keys.length; i < l; i++) {
+      var key = keys[i]
+      cloned[key] = deepClone(obj[key])
+    }
+    return cloned
+  } else {
+    return obj
+  }
+}