Skip to content

基本概念

Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享

State

  • 在 store/ index.js 里定义全局数据
js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0 //定义全局数据
  },
  //mutations 用于变更 Store 中的数据
  mutations: {},
  actions: {},
  modules: {}
})
  • 在组件中使用数据
vue
<!-- 通过 $store.state 使用 -->
<template>
  <div>
    <h3>当前最新的count值为:{{$store.state.count}}</h3>
    <button>+1< /button>
  </div>
</template>
  • 通过 mapState 使用
vue
<template>
  <div>
    <h3>当前最新的count值为:{{ count }}</h3>
    <button>-1</button>
  </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
  data() {
    return {}
  },
  computed: {
    ...mapState(['count'])
  }
}
</script>

Mutation

  • 在 store/ index.js 里定义 mutations 函数
js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0
  },
  //mutations 用于变更 Store 中的数据
  mutations: {
    add(state) {
      state.count += 1
    }
  },
  actions: {},
  modules: {}
})
  • 在组件中调用修改数据
vue
<template>
  <div>
    <h3>当前最新的count值为:{{ $store.state.count }}</h3>
    <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  methods: {
    add() {
      // this.$store.state.count+=1 这种方式会直接修改全局数据不方便后期维护,不能使用这种用法
      //触发 mutations 里的 mutations 函数修改数据,commit 可以调用某个 mutations 函数
      this.$store.commit('add')
    }
  }
}
</script>
  • mutations 可以接收参数
js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0
  },
  //mutations 用于变更 Store 中的数据
  mutations: {
    add(state, stap) {
      state.count += stap
    }
  },
  actions: {},
  modules: {}
})
  • 在组件中调用并传递参数
vue
<template>
  <div>
    <h3>当前最新的count值为:{{ $store.state.count }}</h3>
    <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  methods: {
    add() {
      // 向 mutations 的 add 函数传递参数
      // 传递的参数只能传递一个参数,有多个参数可以放到数组和对象中
      this.$store.commit('add', 3)
    }
  }
}
</script>
  • 第二种方式
  • 在 store/ index.js 里定义 mutations 函数
js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0
  },
  //mutations 用于变更 Store 中的数据
  mutations: {
    sub(state, stap) {
      state.count -= stap
    }
  },
  actions: {},
  modules: {}
})
  • 在组件中调用
vue
<template>
  <div>
    <h3>当前最新的count值为:{{ count }}</h3>
    <button @click="mysub">-1</button>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
export default {
  data() {
    return {}
  },
  computed: {
    ...mapState(['count'])
  },
  methods: {
    ...mapMutations(['sub']),
    mysub() {
      this.sub(3)
    }
  }
}
</script>

不支持异步任务

  • 在 mutations 中不能使用异步代码
js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0
  },
  mutations: {
    sub(state, stap) {
      //在 mutations 中不能使用异步代码
      setTimeout(() => {
        state.count -= stap
      })
    }
  },
  actions: {},
  modules: {}
})

Action

  • 在 store/ index.js 里定义 actions 函数
js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0
  },
  //mutations 用于变更 Store 中的数据
  mutations: {
    add(state, stap) {
      state.count += stap
    },
    sub(state, stap) {
      state.count -= stap
    }
  },

  actions: {
    addAsync(context, n) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('add', n)
      }, 1000)
    }
  },
  modules: {}
})
  • 在组件中调用
vue
<template>
  <div>
    <h3>当前最新的count值为:{{ $store.state.count }}</h3>
    <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  methods: {
    add() {
      // 这里的 dispatch 函数,专门用来触发 action
      this.$store.dispatch('addAsync', 3)
    }
  }
}
</script>
  • actions 函数第二种使用方法

  • 在 store/ index.js 里定义 actions 函数

js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0
  },
  //mutations 用于变更 Store 中的数据
  mutations: {
    add(state, stap) {
      state.count += stap
    },
    sub(state, stap) {
      state.count -= stap
    }
  },

  actions: {
    addAsync(context, n) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('add', n)
      }, 1000)
    }
  },
  modules: {}
})
  • 在组件中调用
vue
<template>
  <div>
    <h3>当前最新的count值为:{{ $store.state.count }}</h3>
    <button @click="addAsync(3)">-1</button>
  </div>
</template>

<script>
import { mapActions } from 'vuex'
export default {
  methods: {
    // 通过 mapActions 可以将 addAsync 函数作为当前组件的私有方法使用
    ...mapActions(['addAsync'])
  }
}
</script>

三者和视图的关系

Getter

  • 相当于 Store 里的计算属性,能将 State 里的数据进行加工然后再返回
  • 在 store/ index.js 里定义 Getter 函数
js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0
  },
  //mutations 用于变更 Store 中的数据
  mutations: {
    add(state, stap) {
      state.count += stap
    },
    sub(state, stap) {
      state.count -= stap
    }
  },

  actions: {
    addAsync(context, n) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('sub', n)
      }, 1000)
    }
  },
  // 定义 getters 函数
  getters: {
    showNum(state) {
      return `当前最新的数量是${state.count}`
    }
  },
  modules: {}
})
  • 在组件中调用 $store.getters.showNum
vue
<template>
  <div>
    <h3>{{ $store.getters.showNum }}</h3>
  </div>
</template>
  • 在 store/ index.js 里定义 Getter 函数
js
export default new Vuex.Store({
  // state 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 state 中进行存储
  state: {
    count: 0
  },
  //mutations 用于变更 Store 中的数据
  mutations: {
    add(state, stap) {
      state.count += stap
    },
    sub(state, stap) {
      state.count -= stap
    }
  },

  actions: {
    addAsync(context, n) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('sub', n)
      }, 1000)
    }
  },
  // 定义 getters 函数
  getters: {
    showNum(state) {
      return `当前最新的数量是${state.count}`
    }
  },
  modules: {}
})
  • 在组件中调用
vue
<template>
  <div>
    <h3>当前最新的count值为:{{ $store.state.count }}</h3>
    <button @click="showNum">-1</button>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
  methods: {
    // 通过 mapGetters 可以将 showNum 函数作为当前组件的私有方法使用
    ...mapGetters(['showNum'])
  }
}
</script>

modules

  • 在全局状态管理 store/index.js 文件中定义
js
export default new Vuex.Store({
  state: {
    count: 100
  },
  mutations: {},
  actions: {},
  getters: {},
  // 当项目很大时可以将 vuex 里的数据进行模块化处理,便于维护
  modules: {
    user: {
      state: {
        token: '123456'
      }
    },
    setting: {
      state: {
        name: 'vuex实例'
      }
    }
  }
})
  • 在其他组件里使用子模块数据
vue
<template>
  <div id="app">
    <p>用户名:{{ $store.state.user.token }}</p>
    <p>应用名:{{ $store.state.setting.name }}</p>
  </div>
</template>
  • 快捷访问方式
  • 在全局状态管理 store/index.js 文件中定义
js
export default new Vuex.Store({
  state: {
    count: 100
  },
  mutations: {},
  actions: {},
  getters: {
    // 我们可以通过之前学过的getters来改变一下,使组件访问更快捷
    token: state => state.user.token,
    name: state => state.setting.name
  },
  // 当项目很大时可以将 vuex 里的数据进行模块化处理,便于维护
  modules: {
    user: {
      state: {
        token: '123456'
      }
    },
    setting: {
      state: {
        name: 'vuex实例'
      }
    }
  }
})
  • 在其他组件里使用子模块数据
vue
<template>
  <div id="app">
    <p>用户名:{{ $store.state.user.token }}</p>
    <p>用户名快捷访问方式:{{ token }}</p>
    <p>应用名:{{ $store.state.setting.name }}</p>
    <p>应用名快捷访问方式:{{ name }}</p>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'app',
  computed: {
    ...mapGetters(['token', 'name'])
  }
}
</script>

调用子模块的 mutations 方法和命名空间

  • 在全局状态管理 store/index.js 文件中定义
js
export default new Vuex.Store({
  getters: {
    token: state => state.user.token
  },
  // 当项目很大时可以将 vuex 里的数据进行模块化处理,便于维护
  modules: {
    user: {
      namespaced: true, // 保证内部模块的高封闭性,添加命名空间,这样这个子模块定义的 mutations 就不是全局的了
      state: {
        token: '123456'
      },
      mutations: {
        // 这里的state表示的是user的state
        updateToken(state) {
          state.token = '5555'
        }
      }
    }
  }
})
  • 在其他组件里使用子模块数据(一)
vue
<template>
  <div id="app">
    <p>用户token:{{ token }}</p>
    <button @click="test">改变token</button>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'app',
  computed: {
    ...mapGetters(['token', 'name'])
  },
  methods: {
    // 方法一
    test() {
      this.$store.commit('user/updateToken') // 直接调用方法
    }
  }
}
</script>
  • 辅助函数方式调用(二)
vue
<template>
  <div id="app">
    <p>用户token:{{ token }}</p>
    <button @click="test">改变token</button>
  </div>
</template>

<script>
import { mapGetters, mapMutations } from 'vuex'

export default {
  name: 'app',
  computed: {
    ...mapGetters(['token', 'name'])
  },
  methods: {
    ...mapMutations(['user/updateToken']),
    test() {
      // 方法二
      this['user/updateToken']() // 辅助函数方式
    }
  }
}
</script>
  • 基于命名空间辅助函数(三)
vue
<template>
  <div id="app">
    <p>用户token:{{ token }}</p>
    <button @click="test">改变token</button>
  </div>
</template>

<script>
import { mapGetters, createNamespacedHelpers } from 'vuex'
const { mapMutations: userMapMutations } = createNamespacedHelpers('user')
export default {
  name: 'app',
  computed: {
    ...mapGetters(['token', 'name'])
  },
  methods: {
    ...userMapMutations(['updateToken']),
    test() {
      // 方法三
      this.updateToken() // 基于命名空间辅助函数
    }
  }
}
</script>