0
点赞
收藏
分享

微信扫一扫

Vuex入门到深入

爱上流星雨 2022-04-03 阅读 61
vue.js

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对象有相似的地方

image-20211211195156425

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总结几点
  • 对于手动操作几点总结
举报

相关推荐

0 条评论