Vuex使用

1.简介

Vuex 状态管理插件

在Vue 最重要就是 数据驱动 和 组件化,每个 组件都有自己 data ,template 和 methods, data是数据,我们也叫做状态,通过methods中方法改变 状态来更新视图,在单个组件中修改状态更新视图是很方便的,但是实际开发中是多个组件(还有多层组件嵌套)共享同一个状态时,这个时候传参就会很繁琐,我们这里就引进 Vuex 来进行状态管理,负责组件中的通信,方便维护代码

Vuex 主要解决的问题

多个视图依赖同一个状态
来自不同视图的行为需要变更同一个状态

使用 Vuex 的好处

能够在 vuex 中集中管理共享的数据,易于开发和后期维护
能够高效地实现组件之间的数据共享,提高开发效率
在 vuex 中的数据都是响应式的

2.Vuex 基础使用

首先在Vue中添加 Vuex 插件

通过 vue-cli 添加了 Vuex 后,在项目的 src 目录下会多出一个 store 目录,目录下会有个 index.js
当然也通过 npm 进行安装 Vuex

npm install vuex --save

在开发环境开启严格模式 这样修改数据 就必须通过 mutation 来处理

在 package.json 文件 scripts 中可以设置环境,当我们处于开发环境时,可以开启严格模式
开启严格模式的方式也是很简单的一行代码就可以

strict:products.env.NODE_ENV !== 'production'
/* src/store/index.js */

// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'

// 把 Vuex 注册到Vue 上
Vue.use(Vuex)

export default new Vuex.Store({
  // 在开发环境开启严格模式 这样修改数据 就必须通过 mutation 来处理
  strict:products.env.NODE_ENV !== 'production',
  // 状态
  state: {
  },
  // 用来处理状态
  mutations: {
  },
  // 用于异步处理
  actions: {
  },
  // 用来挂载模块
  modules: {
  }
})

要使用 store 就在把 store 挂载到 Vue 中

把 store 挂载到 Vue 之后 ,所有的组件就可以直接从 store 中获取全局数据了

import Vue from 'vue'
import App from './App.vue'
import store from './store'

Vue.config.productionTip = false

new Vue({
  // 挂载到vue 中
  store,
  render: (h) => h(App),
}).$mount('#app')

1.state

在 state 中添加数据

我们需要共享的状态都放在写在 state 对象里面

/* src/store/index.js */

// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'

// 把 Vuex 注册到Vue 上
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    name: '张三',
    age: 21,
  },
  mutations: {},
  actions: {},
  modules: {},
})

组件中获取 state 中的数据

获取到 state 有两种方式
1.直接使用 this.$store.state[属性] ,(this 可以省略)

<template>
  <div id="app">
    {{ this.$store.state.name }}
    {{ this.$store.state.age }}
  </div>
</template>

2.使用 mapState
通过 mapState把 store 映射到 组件的计算属性,就相当于组件内部有了 state 里的属性
知道这里为啥要用 …展开吗,到时候实现 mapState 时就知道了

<template>
  <div id="app">
    {{ name }}
    {{ age }}
  </div>
</template>

<script>

// 从 Vuex 中导入 mapState
import { mapState } from 'vuex'
export default {
  name: 'App',
  computed: {
    // 将 store 映射到当前组件的计算属性
    ...mapState(['name', 'age'])
  }
}
</script>

<style  scoped>
</style>

注意

当store 中的值 和 当前组件有相同的状态,我们可以在 mapState 方法里传递一个对象 而不是一个数组,在对象中给状态起别名

computed: {
    // name2 和 age2 都是别名
    ...mapState({ name2: 'name', age2: 'age'}])
}

2.Mutation
Store 中的状态不能直接对其进行操作,我们得使用 Mutation 来对 Store 中的状态进行修改,虽然看起来有些繁琐,但是方便集中监控数据的变化
state 的更新必须是 Mutation 来处理

我们现在 mutaions 里定义个方法

如果想要定义的方法能够修改 Store 中的状态,需要参数就是 state

/* src/store/index.js */

// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'

// 把 Vuex 注册到Vue 上
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    name: '张三',
    age: 21,
  },
  mutations: {
    // 在这里定义 方法
    /**
     *
     * @param {*} state 第一个参数是 Store 中的状态(必须传递)
     * @param {*} newName 传入的参数 后面是多个
     */
    changeName(state, newName) {
      // 这里简单举个例子 修改个名字
      state.name = newName
    },
  },
  actions: {},
  modules: {},
})

在组件中使用 mutations 中的方法

同样有两种方法在组件触发 mutations 中的方法
1.this.$store.commit() 触发
在 methods 中定义一个方法,在这个方法里面进行触发 mutations 中的方法

<template>
  <div id="app">
    <button @click="handleClick">方式1 按钮使用 mutation 中方法</button>
    {{ name }}
  </div>
</template>

<script>

// 从 Vuex 中导入 mapState
import { mapState } from 'vuex'
export default {
  name: 'App',
  computed: {
    // 将 store 映射到当前组件的计算属性
    ...mapState(['name', 'age'])
  },
  methods: {
    handleClick() {
      // 触发 mutations 中的 changeName
      this.$store.commit('changeName', '小浪')
    }
  },
}
</script>

<style  scoped>
</style>

2.使用 mapMutations

<template>
  <div id="app">
    <button @click="changeName('小浪')">方式2 按钮使用 mutation 中方法</button>
    {{ name }}
  </div>
</template>

<script>

// 从 Vuex 中导入 mapState
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'App',
  computed: {
    // 将 store 映射到当前组件的计算属性
    ...mapState(['name', 'age'])
  },
  methods: {
	// 将 mutations 中的 changeName 方法映射到 methods 中,就能直接使用了 changeName 了
    ...mapMutations(['changeName'])
  },
}
</script>

<style  scoped>
</style>

3.Action

Action 和 Mutation 区别

Action 同样也是用来处理任务,不过它处理的是异步任务,异步任务必须要使用 Action,通过 Action 触发 Mutation 间接改变状态,不能直接使用 Mutation 直接对异步任务进行修改

先在 Action 中定义一个异步方法来调用 Mutation 中的方法

/* src/store/index.js */

// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'

// 把 Vuex 注册到Vue 上
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    name: '张三',
    age: 21,
  },
  mutations: {
    // 在这里定义 方法
    /**
     *
     * @param {*} state 第一个参数是 Store 中的状态(必须传递)
     * @param {*} newName 传入的参数 后面是多个
     */
    changeName(state, newName) {
      // 这里简单举个例子 修改个名字
      state.name = newName
    },
  },
  actions: {
    /**
     *
     * @param {*} context 上下文默认传递的参数
     * @param {*} newName 自己传递的参数
     */
    // 定义一个异步的方法 context是 store
    changeNameAsync(context, newName) {
      // 这里用 setTimeout 模拟异步
      setTimeout(() => {
        // 在这里调用 mutations 中的处理方法
        context.commit('changeName', newName)
      }, 2000)
    },
  },
  modules: {},
})

在组件中是 Action 中的异步方法也是有两种方式
1.this.$store.dispatch()

<template>
  <div id="app">
    <button @click="changeName2('小浪')">方式1 按钮使用 action 中方法</button>
    {{ name }}
  </div>
</template>

<script>

// 从 Vuex 中导入 mapState mapMutations
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'App',
  computed: {
    // 将 store 映射到当前组件的计算属性
    ...mapState(['name', 'age'])
  },
  methods: {
    changeName2(newName) {
      // 使用 dispatch 来调用 actions 中的方法
      this.$store.dispatch('changeNameAsync', newName)
    }
  },
}
</script>

<style  scoped>
</style>

2.使用 mapActions

<template>
  <div id="app">
    <button @click="changeNameAsync('小浪')">
      方式2 按钮使用 action 中方法
    </button>
    {{ name }}
  </div>
</template>

<script>

// 从 Vuex 中导入 mapState mapMutations mapActions
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
  name: 'App',
  computed: {
    // 将 store 映射到当前组件的计算属性
    ...mapState(['name', 'age'])
  },
  methods: {
    // 映射 actions 中的指定方法 到 methods中,就可以在该组件直接使用
    ...mapActions(['changeNameAsync'])
  },
}
</script>

<style  scoped>
</style>

4.Getter

简介

Getter 类似于计算属性,但是我们的数据来源是 Vuex 中的 state ,所以就使用 Vuex 中的 Getter 来完成

应用场景

需要对 state 做一些包装简单性处理 展示到视图当中

先来写个 Getter

/* src/store/index.js */

// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'

// 把 Vuex 注册到Vue 上
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    name: '张三',
    age: 21,
  },
  getters: {
    // 在这里对 状态 进行包装
    /**
     *
     * @param {*} state 状态 如果要使用 state 里面的数据,第一个参数默认就是 state ,名字随便取
     * @returns
     */
    decorationName(state) {
      return `大家好我的名字叫${state.name}今年${state.age}`
    },
  },
})

当然 Getter 也有两种方式导入
1.this.$store.getters[名称]

<template>
  <div id="app">
    {{ this.$store.getters.decorationName }}
  </div>
</template>

2.使用 mapGetters

<template>
  <div id="app">
    {{ decorationName }}
  </div>
</template>

<script>

// 从 Vuex 中导入 mapGetters
import { mapGetters } from 'vuex'
export default {
  name: 'App',
  computed: {
    // 将 getter 映射到当前组件的计算属性
    ...mapGetters(['decorationName'])
  },
}
</script>

5.Module
为了避免在一个复杂的项目 state 中的数据变得臃肿,Vuex 允许将 Store 分成不同的模块,每个模块都有属于自己的 state,getter,action,mutation

我们这里新建一个 animal.js 文件

/* animal.js */

const state = {
  animalName: '狮子',
}
const mutations = {
  setName(state, newName) {
    state.animalName = newName
  },
}

//导出
export default {
  state,
  mutations,
}

在 store/index.js中的 modules 进行挂载这个模块

/* src/store/index.js */

// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 引入模块
import animal from './animal'

// 把 Vuex 注册到Vue 上
Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    animal,
  },
})

然后我们就可以在组件中使用了

<template>
  <div id="app">
    {{ this.$store.state.animal.animalName }}
    <button @click="$store.commit('setName', '老虎')">改名</button>
  </div>
</template>

$store.state[在module中挂载的模块名][挂载的模块里的属性]
是不是觉得这种模式很复杂

添加命名空间

其实也可以使用 mapXXX 方法进行映射,不过写法有些许不同,先在导出的添加一个命名空间 namespaced: true

/* animal.js */

const state = {
  animalName: '狮子',
}
const mutations = {
  setName(state, newName) {
    state.animalName = newName
  },
}

export default {
  // 开启命名空间 方便之后使用 mapXXX
  namespaced: true,
  state,
  mutations,
}

方式2

<template>
  <div id="app">
    {{ animalName }}
    <button @click="setName('老鹰')">改名</button>
  </div>
</template>

<script>

// 从 Vuex 中导入 mapState mapMutations
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'App',
  computed: {
    // mapState 使用方式和之前有些许不同,第一个是module挂载的模块名
    // 第二个参数是 animal 模块中的 state 属性
    ...mapState('animal', ['animalName'])
  },
  methods: {
    // mapMutations 使用方式也和之前有些许不同,第一个是module挂载的模块名
    // 第二个参数是 animal 模块中的 mutation 方法
    ...mapMutations('animal', ['setName'])
  },
}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值