vuex讲解

一、vuex基本使用

1. 安装

npm i vuex -S

2. 导入 并 使用到项目中

import Vuex from 'vuex'
vue.use(Vuex)

3. 创建 store 对象

const store = new Vuex.Store({
 state:{ count = 0 } // state 对象里面的就是全局共享数据,如这里的 count
})

4. 将 store 对象挂载到 vue 实例当中

new Vue({
  el: '#app'
  render: h => h(app)
  router
  store  // 此时,所有 vue 项目中的组件均可共享 store 中的数据
})

二、在 vue-cli 创建的 vue 项目中讲解 vuex 的使用

1. 创建后的项目目录简述

store 文件夹里的 index.js 文件如下(相当于自己创建的 store.js 文件):

main.js 文件如下:

2. 核心概念讲解

讲解要素:vuex 中主要核心概念:

  • State
  • Mutations
  • Actions
  • Getters

另外: 有个 modules 节点 

讲解准备:在项目中先创建 Add.vue 和 Sub.vue 组件,并在 App.vue 中导入使用:

  • Add.vue :
<template>
  <div>
    <h3>count =</h3>
    <button>+1</button>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  }
}
</script>
  • Sub.vue :
<template>
  <div>
    <h3>count =</h3>
    <button>-1</button>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  }
}
</script>
  • App.vue :
<template>
  <div>
    <my-add></my-add>
    <p>---------------------</p>
    <my-sub></my-sub>
  </div>
</template>

<script>
// 1. 导入子组件
import Add from '@/components/Add.vue'
import Sub from '@/components/Sub.vue'

export default {
  data() {
    return {}
  },
  components: {
    // 注册私有组件,并重新命名
    'my-add': Add,
    'my-sub': Sub
  }
}
</script>

2.1 State 讲解

State 是唯一的公共数据源。所有共享数据都放在 Store/index.js 的 State 中进行存储。

  • Store/index.js :
import Vue from 'vue'
import Vuex from 'vuex'

// 使用插件
Vue.use(Vuex)

// 存储数据仓库
const state = {
  count: 0 // 共享数据 count
}
// 唯一能对state数据进行修改的地方
const mutations = {}
// 业务逻辑和异步操作
const actions = {}
// 简化仓库数据,相当于计算属性,使得组件获取仓库数据更加方便
const getters = {}

// 对外暴露实例
export default new Vuex.Store({
  state,
  mutations,
  actions,
  getters
})

Add.vue 和 Sub.vue 组件中使用共享数据 count。

  • 1. 通过 this.$store.state.全局数据名称 方式使用

Add.vue :

注:template 中 this 可以省略

<template>
  <div>
    <h3>count = {{ $store.state.count }}</h3>
    <button>+1</button>
  </div>
</template>
  • 2. 通过 mapState 映射函数方式使用

Sub.vue :

<template>
  <div>
    <!-- 3. 使用全局共享数据 -->
    <h3>count = {{ count }}</h3>
    <button>-1</button>
  </div>
</template>

<script>
// 1. 导入 mapState 函数
import { mapState } from 'vuex'

export default {
  data() {
    return {}
  },
  // 2. 在计算属性节点映射全局共享数据,并用展开运算符展开
  computed: {
    ...mapState(['count'])
  }
}
</script>

2.2 Mutations 讲解

任何时候都不要直接去修改 State 里面的数据,否则可能会造成不必要的意外,也不利于后期维护。例如:

<template>
  <div>
    <h3>count = {{ $store.state.count }}</h3>
    <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  },
  methods: {
    add() {
      this.$store.state.count++  // 切记不要这样
    }
  }
}
</script>

因此,Mutation 出现了,它用于变更 Store 中的数据。

Store/index.js :

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0 // 共享数据 count
  },
  getters: {},
  mutations: {
    // 定义 add() 方法
    add(state) {
      // 变更状态
      state.count++
    }
  },
  actions: {},
  modules: {}
})

Mutations 里的函数也可以传参:

  mutations: {
    // 第一个参数永远是 state ,第二个参数是传进来的参数
    addN(state,step) {
      state.count += step
    }
  },
  • 1. 使用 this.$store.commit() 方式调用方法

App.vue :

<template>
  <div>
    <h3>count = {{ $store.state.count }}</h3>
    <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  },
  methods: {
    add() {
      this.$store.commit('add') // commit() 作用就是调用 Store 中的函数
    }
  }
}
</script>

使用时候传参:

  methods: {
    add() {
      this.$store.commit('addN',5) // 5 是传参
    }
  }
  • 2. 使用 mapMutations 映射方式调用方法

 Sub.vue :

<template>
  <div>
    <h3>count = {{ count }}</h3>
    <button @click="subclick">-1</button>
  </div>
</template>

<script>
// 1. 导入 mapMutations 函数
import { mapState, mapMutations } from 'vuex'

export default {
  data() {
    return {}
  },
  computed: {
    ...mapState(['count'])
  },
  // 2. 在 methods 节点映射全局共享数据,并用展开运算符展开。然后调用。
  methods: {
    ...mapMutations(['sub']),
    subclick() {
      this.sub()
    }
  }
}
</script>

2.3 Actions 讲解

看看下面,我们在 Store/index.js 里的 mutations 里进行异步操作。其实这样是不行的!!

export default new Vuex.Store({
  state: {
    count: 0 // 共享数据 count
  },
  getters: {},
  mutations: {
    addN(state, step) {
      // 不要在 mutations 进行异步操作
      // setTimeout(function () {
      //   state.count += step
      // }, 1000)
    },
    sub(state) {
      state.count--
    }
  },
  actions: {},
  modules: {}
})

 在 vuex 中,如果要通过异步操作变更数据,必须通过 Actions,在 Actions  中触发 Mutations 的方式间接变更数据。

Store/index.js :

export default new Vuex.Store({
  state: {
    count: 0 // 共享数据 count
  },
  mutations: {
    add(state) {
      state.count++
    },
    addN(state,step) {
      state.count += step
    }
  },
  actions: {
    addAsync(context) {
      setTimeout(() => {
        context.commit('add') // 触发 mutations 中的函数
      }, 1000)
    }
  },
})

接收参数:

actions: {
    addAsync(context,step) {  // step 接收组件中传过来的参数
      setTimeout(() => {
        context.commit('addN',step) // step 是将上面的参数传到 mutations 中的函数中
      }, 1000)
    }
  }
  • 1. 使用 this.$store.dispatch() 触发 actions 中的函数

App.vue :

<template>
  <div>
    <h3>count = {{ $store.state.count }}</h3>
    <button @click="addAsc">+5</button>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  },
  methods: {
    addAsc() {
      this.$store.dispatch('addAsync') // 使用 dispatch 触发 actions 中的函数
    }
  }
}
</script>

传参:

  methods: {
    addAsc() {
      this.$store.dispatch('addAsync',5) // 使用 dispatch 触发 actions 中的函数
    }
  }
  • 2. 使用 mapActions 映射方式触发 actions 中的函数
<template>
  <div>
    <h3>count = {{ $store.state.count }}</h3>
    <button @click="addAsync()">+5</button>
  </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  data() {
    return {}
  },
  methods: {
    ...mapActions(['addAsync']),
  }
}
</script>

2.4 Getters 讲解

Getters 用于对 Store 中的数据进行加工,形成新的数据,类似于  vue 中的计算属性。

Store 中的数据发生变化,Getter 的数据也会跟着变化。

Store/index.js :

  getters: {
    showNum(state) {
      return '当前的值为:' + state.count
    }
  }
  • 1. 通过 $store.getters.方法名称 方式使用

Add.vue :

<template>
  <div>
    <h3>{{ $store.getters.showNum }}</h3>
  </div>
</template>
  • 2. 通过mapGetters 映射方式使用
<template>
  <div>
    <!-- 3. 使用 -->
    <h3>count = {{ count }}</h3>
  </div>
</template>

<script>
// 1. 导入函数
import { mapGetters } from 'vuex'

export default {
  data() {
    return {}
  },
  // 2. 在计算属性节点映射全局共享数据,并用展开运算符展开
  computed: {
    ...mapGetters(['showNum'])
  }
}
</script>

2.5 modules 讲解

modules:项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

const moduleA ={
state:{...},
mutations:{...},
actions:{...},
getters:{...}
}
const moduleB ={
state:{...},
mutations:{...},
actions:{...}
}
const store =newVuex.Store({
modules:{
a: moduleA,
b: moduleB
})

或者,每一个模块在相对应组件文件夹下建立对象的store模块(小仓库),然后在主仓库引入进来,再暴露出去。

import Vue from 'vue'
import Vuex from 'vuex'

// 使用插件
Vue.use(Vuex)

// 引入小仓库
import homeStore from './home/homeStore'
import searchStore from './search/searchStore'

// 对外暴露小仓库
export default new Vuex.Store({
  modules: {
    homeStore,
    searchStore
  }
})

 

posted @ 2022-05-17 17:26  RHCHIK  阅读(49)  评论(0编辑  收藏  举报