vuex插件的学习
1.目的:$bus不善于处理组件过多时的数据通信,vuex的引入目的在于更好的实现多组件之间的数据共享
2.运作原理:vuex类似于全局变量,将要共享的数据及其操作方法独立出去,实现共享数据与组件解耦
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JWdMmiO5-1648954916682)(…/…/%E8%B5%84%E6%96%99%EF%BC%88%E5%90%AB%E8%AF%BE%E4%BB%B6%EF%BC%89/02_%E5%8E%9F%E7%90%86%E5%9B%BE/vuex.png)]
3.使用步骤:
- 下载:npm install vuex -s
 - 导入插件:import Vuex from ‘vuex’
 - 注册插件:Vue.use(Vuex)
 - 挂载store:
 - 创建store对象
 
4.vuex中的角色:
5.基础演示
<template>
  <div>
    <h1>当前求和为:{{ sum }}</h1>
    <h1>当前求和十倍为:{{ bigSum }}</h1>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment(n)">+</button>
    <button @click="decrement(n)">-</button>
    <button @click="incrementOdd(n)">当前求和为奇数再加</button>
    <button @click="incrementWait(n)">等一等再加</button>
  </div>
</template>
  data() {
    return {
      n: 1, // 用户选择的数字
    }
  },
  methods: {
    // 调用加的方法
    increment() {
      this.$store.commit('ADD', this.n)
    },
    // 调用减的方法
    decrement() {
      this.$store.commit('SUB', this.n)
    },
    // 奇数再加
    incrementOdd() {
      this.$store.dispatch('oddAdd', this.n)
    },
    // 延迟加
    incrementWait() {
      this.$store.dispatch('waitAdd', this.n)
    },
  },
  computed: {
    sum() {
      return this.$store.state.sum
    },
    bigSum() {
      return this.$store.getters.bigSum
  },
store.js:
// 状态
const state = {
  sum: 0,
}
// 响应者
const actions = {
  // context是上下文,上下文即是vue封装的相关信息对象
  // value是附带的参数
  oddAdd(context, value) {
    console.log('我处理了一些事,其它交给oddAddExpand处理')
    // 业务逻辑比较复杂可以开启职责链模式,这也是为什么这里的参数是       context而不直接是commit
    context.dispatch('oddAddExpand', value)
  },
  oddAddExpand(context, value) {
    context.state.sum % 2 !== 0 && context.commit('ODDADD', value)
  },
  waitAdd(context, value) {
    setTimeout(() => {
      context.commit('WAITADD', value)
    }, 2000)
  },
}
// 操作者
const mutations = {
  // state是状态,value是commit附带的参数
  ADD(state, value) {
    state.sum += value
  },
  SUB(state, value) {
    state.sum -= value
  },
  ODDADD(state, value) {
    state.sum += value
  },
  WAITADD(state, value) {
    state.sum += value
  },
}
// 数据装饰者,是在业务处理后对数据做最后处理的对象
const getters = {
  bigSum(state) {
    return state.sum * 10
  },
}
6.开发者工具使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FcN117Wb-1648954916683)(…/…/…/…/AppData/Roaming/Typora/typora-user-images/image-20211211201536591.png)]
7.进阶演示
8.map的使用
- 
mapState
写法: …mapState([‘personList’]) 或…mapState({personList:‘personList’})
等价于: personList=function(){return this.$store.state.personList}
 - 
mapActions同理
 - 
mapMutations同理
 - 
mapGetters同理
 
9.模块化
- 
 加减模块
// 加减业务模块 export default { namespaced: true, state: { sum: 0 }, getters: { // 数据装饰者,是在业务判断后对数据做最后处理的角色 bigSum(state) { return state.sum * 10 }, }, actions: { // context是上下文,上下文即是vue封装的相关信息对象 // value是附带的参数 oddAdd(context, value) { console.log('我处理了一些事,其它交给oddAddExpand处理') // 业务逻辑比较复杂可以开启职责链模式,这也是为什么这里的参数是context而不直接是commit context.dispatch('oddAddExpand', value) }, oddAddExpand(context, value) { context.state.sum % 2 !== 0 && context.commit('ODDADD', value) }, waitAdd(context, value) { setTimeout(() => { context.commit('WAITADD', value) }, 2000) }, }, mutations: { // context是上下文,是vue提供的可能需要的对象 ADD(state, value) { state.sum += value }, SUB(state, value) { state.sum -= value }, ODDADD(state, value) { state.sum += value }, WAITADD(state, value) { state.sum += value }, }, } - 
人员管理模块
// 人员管理业务模块 export default { namespaced: true, state: { personList: [ { id: 1, name: 'wz' }, { id: 2, name: 'lh' }, { id: 3, name: 'xm' }, ], }, getters: { enhancePerson(state) { const persons = [ { id: 1, name: 'wzxxx' }, { id: 2, name: 'lhxxx' }, { id: 3, name: 'xmxxx' }, ] return persons }, }, actions: { addWang(context, value) { if (value.name.indexOf('王') === 0) { context.commit('ADD_PERSON', value) } else { alert('必须兴姓王') } }, }, mutations: { ADD_PERSON(state, value) { state.personList.push(value) }, }, } - 
store导入各模块
// 导入vue原型 import Vue from 'vue' // 导入Vuex原型 import Vuex from 'vuex' // 导入加减模块 import countOptions from './count' // 导入人员管理模块 import personOptions from './person' // 使用插件 Vue.use(Vuex) // 创建并导出vuex的管理者store export default new Vuex.Store({ // 模块化 modules: { countModule: countOptions, personModule: personOptions }, }) - 
使用演示
map方式获取数据方法
mapState的使用
computed: { //等价于 personList=function(){return this.$store.state['personModule/personList']} ...mapState('personModule', ['personList']), },mapGetters的使用
```javascript ...mapGetters('countModule', ['bigSum']), ```mapMutations的使用
methohs:{ // 等价于 increment(){this.&store.commit('countModule/ADD')} ...mapMutations('countModule', { increment: 'ADD', decrement: 'SUB' }), }mapActions的使用
// 奇数再加 ...mapActions('countModule', { incrementOdd: 'oddAdd', incrementWait: 'waitAdd' }),手动方式获取数据方法
执行mutations
this.$store.commit('personModule/ADD_PERSON', personObj)执行actions
this.$store.dispatch('personMoudule/addWang', personObj)执行getters
enhancdPerson() { return this.$store.getters['personModule/enhancePerson'] },执行state
sum() { return this.$store.state['countModule/sum']}, 
8.异步请求
 界面
          ```html          <template>            <div>              <button @click="findTalk({ pageNum: 1, pageSize: 6 })">获取说说</button>              <div v-for="talk in talkList" :key="talk.id">{{ talk.content }}</div>            </div>          </template>          <script>          import { mapState, mapActions } from 'vuex'          export default {            computed: {              ...mapState('talkModule', ['talkList']),            },            methods: {              ...mapActions('talkModule', ['findTalk']),            },          }          </script>          ```
 store中的talk模块action发起异步请求
 配置vue-cli代理服务器解决同源问题
  ```javascript  module.exports = {    // 配值代理服务器    devServer: {      proxy: {        '/talk': {          target: 'http://www.xxx.com',        },      },    },  }  ```
 actions中发起异步请求, 成功时回调mutaptions中的方法,填入数据
// 导入axiosimport axios from 'axios'export default {  namespaced: true,  state: {    talkList: [],  },  actions: {    // 获取说说请求    findTalk(context, value) {      axios        .get('talk/findTalkByPage', {          params: value,        })        .then(          (resonse) => {            // 解构赋值            const { data } = resonse            const talks = data.talkList            // 调用mutations处理数据            context.commit('FINDTALK', talks)          },          (error) => {            console.log(error)          }        )    },  },  mutations: {    FINDTALK(state, talks) {      // 清空原来的      state.talkList = []      // 填入数据      talks.forEach((talk) => {        state.talkList.push(talk)      })    },  },}
 store导入talk模块并且注册
 ```javascript // 导入vue原型 import Vue from 'vue' // 导入Vuex原型 import Vuex from 'vuex' // 导入加减模块 import countOptions from './count' // 导入人员管理模块 import personOptions from './person' // 导入说说管理模块 import talkOptions from './talk' // 使用插件 Vue.use(Vuex) // 创建并导出vuex的管理者store export default new Vuex.Store({   // 模块化   modules: { countModule: countOptions, personModule: personOptions, talkModule: talkOptions }, }) ```
7.常见问题
①创建store之间一定要先使用vuex,因为import会提升
②要注意actions中的参数是context和value而mutations中的参数是state和value
③模块化的时候一定要加上命名空间namespaced:true,并且创建store时加上modules:{}
8.重点
context: actions的参数有一个是context,这个参数是上下文对象,所谓上下问对象即是vue为方便操作而封装的相关信息对象,与事件触发时event对象有相似的地方

9.其中用到的设计模式的思考
①职责链模式
在actions可以链式调用方法进行业务处理
  oddAdd(context, value) {    console.log('我处理了一些事,其它交给oddAddExpand处理')    // 业务逻辑比较复杂可以开启职责链模式,这也是为什么这里的参数是       context而不直接是commit    context.dispatch('oddAddExpand', value)  },  oddAddExpand(context, value) {    context.state.sum % 2 !== 0 && context.commit('ODDADD', value)  },
②装饰器模式
// 数据装饰者,是在业务处理后对数据做最后处理的对象const getters = {  bigSum(state) {    return state.sum * 10  },}
10.总结**
Vuex是组件共享数据的一种解决方案其通过store来管理共享数据,其中
- state是保存共享数据的角色,里面保存了组件之间要共享的数据
 - actions是进行业务逻辑判断的角色,主要进行逻辑判断选择调用哪个方法
 - mutations数据操作角色,里面封装了共享数据操作方法
 - getter数据装饰者,在业务逻辑处理完成后对数据进行最后操作的的角色
 
我们将store的挂载在Vue原型后,就可以使用this.$store来操作共享数据了,vuex会在状态变更时重新渲染页面
同时我们还可以进行模块化,仅仅需要配置再store中一个modules并导入对应模块就可以
- 对于map总结几点
 
- 对于手动操作几点总结
 










