Vuex的使用较为详尽(部分方法较重复未写出)

Vuex的使用

简单的简历一个store仓库

在文件夹store下面的index.js写入如下代码。

import Vue from 'vue'
import Vuex from 'vuex'
// 全局注册插件
Vue.use(Vuex)
export default new Vuex.Store({
    state: {
        count: 0,
        age: 18
    }
})

上面约等于在状态管理中全局挂在了该store,需要使用的时候可以直接调来使用。

获取状态

<template>
  <div>
    <p>the count is {{count}}</p>
    <p>the age is {{age}}</p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      count: 0,
      age: 0
    }
  },
  mounted() {
    console.log(this.$store) // 打印出store 可以看到里面有个state,可以来获取state中的参数然后给初始化的data进行赋值
    this.count = this.$store.state.count
    this.age = this.$store.state.age
  }
}
</script>

上面代码中是通过this.$store.state.count来获取的状态

mapState获取状态

<template>
  <div>
    <p>the count is {{count}}</p>
    <p>the age is {{age}}</p>
  </div>
</template>
<script>
import { mapState } from 'vuex'
export default {
  data() {
    return {
      // count: 10,
      // age: 0
    }
  },
  mounted() {
    console.log(this.$store)
    // this.count = this.$store.state.count
    // this.age = this.$store.state.age
  },
  methods: {
    getState () {
      console.log(this.count) // 获取count的值
    }
  },
  computed: {
    ...mapState(['count', 'age']) // 通过辅助函数来获取相关的,参数为一个数组,数组内字符串表示获取的状态,获取后直接会挂载到this上面,通过this.count即可获取
  }
}
</script>

上面说了获取,下面来说明如何实现修改状态。

修改状态

// store/index.js 如下修改
export default new Vuex.Store({
  state: {
    count: 0,
    age: 18
  },
  mutations: {
    addCount (state, upload) { // 用来触发修改的函数,upload为传递过来的参数
      state.count += upload // 官方建议载荷upload应该为对象  次数使用值
    }
  }
})
// 调用的组件
<template>
  <div>
    <p>the count is {{count}}</p>
    <p>the age is {{age}}</p>
    <button @click='getState'>count</button>
    <button @click='changeCount(10)'>addCount</button> 
  </div>
</template>
<script>
import { mapState } from 'vuex'
export default {
  data() {
    return {
      // count: 10,
      // age: 0
    }
  },
  mounted() {
    // console.log(this.$store)
    // this.count = this.$store.state.count
    // this.age = this.$store.state.age
  },
  methods: {
    getState () {
      console.log(this.count)
    },
    changeCount (x) {
      this.$store.commit('addCount', x)// 使用commit来提交mutation,从而修改状态
    }
  },
  computed: {
    ...mapState(['count', 'age'])
  }
}
</script>

其实修改状态的方法只有一种,就是提交mutation

mutation辅助函数

// (为了代码完整,复制可用,使用的完整子组件代码)
<template>
  <div>
    <p>the count is {{count}}</p>
    <p>the age is {{age}}</p>
    <button @click='getState'>count</button>
    <button @click='changeCount(10)'>addCount</button> 
    <button @click='changeAge(10)'>addAge</button> 
  </div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
  data() {
    return {
      // count: 10,
      // age: 0
    }
  },
  mounted() {
    // console.log(this.$store)
    // this.count = this.$store.state.count
    // this.age = this.$store.state.age
  },
  methods: {
    getState () {
      console.log(this.count)
    },
    ...mapMutations({
      changeCount: 'addCount', // 将mutation的addCount映射为这里的changeCount
      changeAge: 'addAge' // addAge映射为changeAge
    })
    // changeCount (add) {
    //   this.$store.commit('addCount', add)
    // }
  },
  computed: {
    ...mapState(['count', 'age'])
  }
}
</script>

action的使用

// 下列代码中写到mutations中
resetAge (state) {
    console.log('我是被触发了的')
    setTimeout(() => {
        state.age = 0
    }, 3000) // 三秒后重置年龄
}
// 添加一个button来触发
    <button @click="zeroAge">age0</button>
// 组件内map函数在映射一个zeroAge
...mapMutations({
    changeCount: 'addCount',
    changeAge: 'addAge',
    zeroAge: 'resetAge'
})

本次测试中完全没问题,状态被修改 为0,并且Vue.js devtools中的状态还是被修改了,但是可能会导致调试工具状态不更新的问题。根据官方建议:异步操作在action中使用

使用方法如下:

// mutation 中添加
zeroAge(state) {
    console.log(state)
    state.age = 0
}
// action中添加出发mutation的方法
actions: {
    resetAge (content) {
        console.log('content', content)
        setTimeout(() => {
            content.commit('zeroAge')
        }, 3000)
    }
}
// 组件中调用方法使用this.$store.dispatch('触发action事件的名字') button中使用该事件(zeroAge)
zeroAge() {
    this.$store.dispatch('resetAge')
}

注意:修改状态只能在mutations中,因此actions知识用来异步触发mutations的

使用辅助函数mapActions

// 引入这里就不写了,直接在methods里面添加
...mapActions({
    zeroAge: 'resetAge' // 将action 映射为方法zeroAge, 使用即可触发。
})

getters的使用

// 这里在state中添加一个数组,利用getters来获取过滤后的数据
state: {
    count: 0,
        age: 18,
            list: [55, 66, 77, 88, 87, 25]
},
getters: {
    getList(state) {
        eturn state.list.filter(item => item > 75)
    }
}
// 组件中进行使用
computed: {
    ...mapState(['count', 'age']), //之前的代码
    getList() { // 直接可以使用getList数据
      console.log(this.$store.getters.getList)
      return this.$store.getters.getList
    }
}
// 渲染模板中使用getList来渲染过滤后的数据
<p v-for="(item, index) in getList" :key="index">{{item}}</p>

mapGetters的使用和mapState相同,此处不再赘述。

最后的module

这个模块十分重要,对于程序的模块化管理和可读性都有很大帮助

// 这里不再额外敲代码了 直接使用定义的store里面的数据复制到两个module里面
const moduleL = {这里复制store里面的数据即可}
const moduleX = {这里复制store里面的数据即可}
// 将第一号的模块放入module(store的)中
modules: {
    moduleL,
    moduleX
}
// 组件中定义方法来触发
// 直接使用changeCount来进行测试 需要再之前的store和模块中的mutations的addCount增加一句 console.log('muduleL里面的addCount'),console.log('muduleX里面的addCount'),console.log('store里面的addCount')
...mapMutations({
    changeCount: 'addCount',
    changeAge: 'addAge'
})
// 利用button 触发事件  发现很神奇的一幕,打印结果如下所示
store里面的addCount
muduleL里面的addCount
muduleX里面的addCount
// 因此可以推断出会触发所有定义相同名称的mutations,因为Mutations和actions的触发是不区分模块的,因此不能使用相同的名称,否则都会触发。
// 解决办法  使用命名空间
// 在模块内添加:namespaced: true
// 添加命名空间(每个模块内)
namespaced: true,
// 这里再次去触发按钮,触发结果如下
    store里面的addCount 
// 只会触发store里面,命名空间生效了
// 接下来看如何触发每个模块中的mutations,我将他放入的mounted中,页面加载的时候即触发
this.$store.commit('moduleX/addCount', 10)// 即可触发moduleX模块内的addCount
// 使用辅助函数来触发,mapState来映射出数据
...mapState('moduleX', {
    moduleXcount: state => state.count
})
// 辅助函数mapMutation来定义出响应的commit
...mapMutations('moduleX',
   {
     clickMX: 'addCount'
   }
)

下面提供响应的完整的测试代码,抽离文件和常量化根据个人习惯进行设置

// 组件代码
<template>
  <div>
    <p>the count is {{count}}</p>
    <p>the age is {{age}}</p>
    <p>这个是ModuleX里面的count 初次渲染 {{moduleXa}}</p>
    <p>这个是ModuleX里面的count {{moduleXcount}}</p>
    <p v-for="(item, index) in getList" :key="index + 's'" >{{item}}</p>
    <button @click='getState'>count</button>
    <button @click='getAge'>age</button>
    <button @click='changeCount(10)'>addCount</button>
    <button @click='changeAge(10)'>addAge</button>
    <button @click="zeroAge">age0</button>
    <button @click="clickMX(15)">改变moduleX的count</button>
  </div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
  data() {
    return {
      // count: 10,
      // age: 0
      myList: [],
      moduleXa: 0
    }
  },
  mounted() {
    this.$store.commit('moduleX/addCount', 10)
    this.moduleXa = this.$store.state.moduleX.count
    console.log(this.moduleXa)
    // console.log(this.$store)
    // this.count = this.$store.state.count
    // this.age = this.$store.state.age
  },
  methods: {
    ...mapMutations('moduleX',
      {
        clickMX: 'addCount'
      }
    ),
    getState () {
      console.log(this.count)
    },
    getAge() {
      console.log(this.age)
    },
    ...mapMutations({
      changeCount: 'addCount',
      changeAge: 'addAge'
    }),
    // zeroAge() {
    //   this.$store.dispatch('resetAge')
    // }
    ...mapActions({
      zeroAge: 'resetAge'
    })
    // changeCount (add) {
    //   this.$store.commit('addCount', add)
    // }
  },
  computed: {
    ...mapState(['count', 'age']),
    ...mapState('moduleX', {
      moduleXcount: state => state.count
    }),
    getList() {
      console.log(this.$store.getters.getList)
      return this.$store.getters.getList
    }
  }
}
</script>
// store/index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
// import { ADD_COUNT, SUB_COUNT, ASYNCCOUNT } from './mutation_type'
Vue.use(Vuex)
const moduleL = {
  // 添加命名空间
  namespaced: true,
  state: {
    count: 0,
    age: 18,
    list: [55, 66, 77, 88, 87, 25]
  },
  mutations: {
    addCount (state, upload) {
      console.log('muduleL里面的addCount')
      state.count += upload
    },
    addAge(state, upload) {
      state.age += upload
    },
    zeroAge(state) {
      state.age = 0
    }
  },
  actions: {
    resetAge (content) {
      console.log('content', content)
      setTimeout(() => {
        content.commit('zeroAge')
      }, 3000)
    }
  }
}
const moduleX = {
  // 添加命名空间
  namespaced: true,
  state: {
    count: 0,
    age: 18,
    list: [55, 66, 77, 88, 87, 25]
  },
  mutations: {
    addCount (state, upload) {
      console.log('muduleX里面的addCount')
      state.count += upload
    },
    addAge(state, upload) {
      state.age += upload
    },
    zeroAge(state) {
      state.age = 0
    }
  },
  actions: {
    resetAge (content) {
      console.log('content', content)
      setTimeout(() => {
        content.commit('zeroAge')
      }, 3000)
    }
  }
}
export default new Vuex.Store({
  state: {
    count: 0,
    age: 18,
    list: [55, 66, 77, 88, 87, 25]
  },
  getters: {
    getList(state) {
      return state.list.filter(item => item > 75)
    }
  },
  mutations: {
    addCount (state, upload) {
      console.log('store里面的addCount')
      state.count += upload
    },
    addAge(state, upload) {
      state.age += upload
    },
    zeroAge(state) {
      state.age = 0
    }
  },
  actions: {
    resetAge (content) {
      console.log('content', content)
      setTimeout(() => {
        content.commit('zeroAge')
      }, 3000)
    }
  },
  modules: {
    moduleL,
    moduleX
  }
})

简易的抽离文件和常量化(方便定位错误),这个是以前测试使用,不是十分晚上的分离,仅供参考

// 组件代码
<template>
  <div>
    <p>this is count from store is{{this.$store.state.count}}</p>
    <p>准备提交commit 来修改count的值</p>
    <button @click='ADD_COUNT(5)'>提交mutation来修改count的值++</button>
    <button @click='SUB_COUNT(5)'>提交mutation来修改count的值--</button>
    <button @click="ASYNCCOUNT">异步提交mutation</button>
  </div>
</template>
<script>
import { mapMutations, mapActions } from 'vuex'
import { ADD_COUNT, SUB_COUNT, ASYNCCOUNT } from '@/store/mutation_type'
export default {
  mounted () {
    console.log(this.$store)
  },
  // 计算属性的方式来提交mutation
  computed: {
  },
  // 下面是直接用函数的方法来提交mutation
  methods: {
  //   addCount (x) {
  //     this.$store.commit(ADD_COUNT, x)
  //   },
  //   subCount (x) {
  //     this.$store.commit(SUB_COUNT, x)
  //   },
  //   asyncCount () {
  //     this.$store.dispatch(ASYNCCOUNT)
    ...mapMutations([ADD_COUNT, SUB_COUNT]),
    ...mapActions([ASYNCCOUNT])
  //   }
  }
}
</script>
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import { ADD_COUNT, SUB_COUNT, ASYNCCOUNT } from './mutation_type'
export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    [ADD_COUNT] (state, x) {
      state.count += x
    },
    [SUB_COUNT] (state, x) {
      state.count -= x
    },
    [ASYNCCOUNT] (state) {
      state.count = 0
    }
  },
  actions: {
    [ASYNCCOUNT] (content) {// 这里是个不完美的配置 没有单独的配置一个actions的常量文件
      console.log(content)
      setTimeout(() => { content.commit(ASYNCCOUNT) }, 5000)
    }
  },
  modules: {
  }
})

mutation_type.js文件

export const ADD_COUNT = 'ADD_COUNT'
export const SUB_COUNT = 'SUB_COUNT'
export const ASYNCCOUNT = 'ASYNCCOUNT'
暂无评论