Parcourir la source

also expose getters inside getters

Evan You il y a 8 ans
Parent
commit
de2070dcbf
4 fichiers modifiés avec 44 ajouts et 25 suppressions
  1. 2 2
      examples/counter/Counter.vue
  2. 7 5
      examples/counter/store.js
  3. 28 13
      src/index.js
  4. 7 5
      test/unit/test.js

+ 2 - 2
examples/counter/Counter.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    Clicked: {{ count }} times
+    Clicked: {{ $store.state.count }} times, count is {{ evenOrOdd }}.
     <button @click="increment">+</button>
     <button @click="decrement">-</button>
     <button @click="incrementIfOdd">Increment if odd</button>
@@ -13,7 +13,7 @@ import { mapGetters, mapActions } from 'vuex'
 
 export default {
   computed: mapGetters([
-    'count'
+    'evenOrOdd'
   ]),
   methods: mapActions([
     'increment',

+ 7 - 5
examples/counter/store.js

@@ -43,14 +43,16 @@ const actions = {
   }
 }
 
+// getters are functions
+const getters = {
+  evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
+}
+
 // A Vuex instance is created by combining the state, mutations, actions,
-// and getters. Components should prefer interacting with the store via
-// getters and actions.
+// and getters.
 export default new Vuex.Store({
   state,
-  getters: {
-    count: state => state.count
-  },
+  getters,
   actions,
   mutations
 })

+ 28 - 13
src/index.js

@@ -246,7 +246,7 @@ function initStoreState (store, state, getters) {
   Object.keys(getters).forEach(key => {
     const fn = getters[key]
     // use computed to leverage its lazy-caching mechanism
-    computed[key] = () => fn(store._vm.state)
+    computed[key] = () => fn(store)
     Object.defineProperty(store.getters, key, {
       get: () => store._vm[key]
     })
@@ -265,27 +265,40 @@ function initStoreState (store, state, getters) {
 }
 
 function extractModuleGetters (getters = {}, modules = {}, path = []) {
-  if (!modules) return getters
+  if (!path.length) {
+    wrapGetters(getters, getters, path, true)
+  }
+  if (!modules) {
+    return getters
+  }
   Object.keys(modules).forEach(key => {
     const module = modules[key]
     const modulePath = path.concat(key)
     if (module.getters) {
-      Object.keys(module.getters).forEach(getterKey => {
-        const rawGetter = module.getters[getterKey]
-        if (getters[getterKey]) {
-          console.error(`[vuex] duplicate getter key: ${getterKey}`)
-          return
-        }
-        getters[getterKey] = function wrappedGetter (state) {
-          return rawGetter(getNestedState(state, modulePath), state)
-        }
-      })
+      wrapGetters(getters, module.getters, modulePath)
     }
     extractModuleGetters(getters, module.modules, modulePath)
   })
   return getters
 }
 
+function wrapGetters (getters, moduleGetters, modulePath, force) {
+  Object.keys(moduleGetters).forEach(getterKey => {
+    const rawGetter = moduleGetters[getterKey]
+    if (getters[getterKey] && !force) {
+      console.error(`[vuex] duplicate getter key: ${getterKey}`)
+      return
+    }
+    getters[getterKey] = function wrappedGetter (store) {
+      return rawGetter(
+        getNestedState(store.state, modulePath), // local state
+        store.getters, // getters
+        store.state // root state
+      )
+    }
+  })
+}
+
 function enableStrictMode (store) {
   store._vm.$watch('state', () => {
     assert(store._committing, `Do not mutate vuex store state outside mutation handlers.`)
@@ -301,7 +314,9 @@ function isPromise (val) {
 }
 
 function getNestedState (state, path) {
-  return path.reduce((state, key) => state[key], state)
+  return path.length
+    ? path.reduce((state, key) => state[key], state)
+    : state
 }
 
 function install (_Vue) {

+ 7 - 5
test/unit/test.js

@@ -486,10 +486,9 @@ describe('Vuex', () => {
 
   it('module: getters', function () {
     const makeGetter = n => ({
-      [`getter${n}`]: (state, rootState) => {
-        if (rootState) {
-          expect(rootState).to.equal(store.state)
-        }
+      [`getter${n}`]: (state, getters, rootState) => {
+        expect(getters.constant).to.equal(0)
+        expect(rootState).to.equal(store.state)
         return state.a
       }
     })
@@ -497,7 +496,10 @@ describe('Vuex', () => {
       state: {
         a: 1
       },
-      getters: makeGetter(1),
+      getters: {
+        constant: () => 0,
+        ...makeGetter(1)
+      },
       modules: {
         nested: {
           state: { a: 2 },