快速上手Vuex

1.简介

Vuex 是状态管理插件

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

Vuex 主要解决的问题

a.多个视图依赖同一个状态

b.来自不同视图的行为需要变更同一个状态

使用 Vuex 的好处

a.能够在 vuex 中集中管理共享的数据,易于开发和后期维护

b.能够高效地实现组件之间的数据共享,提高开发效率

c.在 vuex 中的数据都是响应式的

2.Vuex 基础使用

首先在Vue中添加vuex插件,一般通过npm安装vuex

npm install vuex --save

在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

通过 mapStatestore 映射到 组件的计算属性,就相当于组件内部有了 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 中的状态进行修改,虽然看起来有些繁琐,但是方便集中监控数据的变化,当中有devtools工具来监测它

state 的更新必须是 Mutation 来处理

我们现在 mutations 里定义个方法

如果想要定义的方法能够修改 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

ActionMutation 区别

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 分成不同的模块,每个模块都有属于自己的 stategetteractionmutation

我们这里新建一个 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>

3.关于vuex的持久化

简介

Vuex本质:一个保存在内存中的对象可以理解成一个全局变量,全局变量也可能产生内存泄漏,存在的问题:当页面刷新后该对象就会被重新初始化,之前存的数据就拿不到了,于是在使用这些数据的地方就可能发生报错

解决方法:把state中的数据做一个持久化存储或者说备份;

一般就存在localStorage、sessionStorage或者cookies中;

这里以localStorage为例

存localStorage的话,数据不会因为页面或浏览器的关闭而丢失,只有手动清除;

在Vuex初始化的时候就尝试去localStorage里面读取之前的数据,再存回state中;

这样当页面刷新或关闭后再打开时,state中还是有之前的数据;

存sessionStorage的话,数据会在页面关闭后被清除;

这些方式都可以自己手动实现,但使用一些第三方插件实现和管理起来会更方便

vuex-persistedstate、 vuex-persist

插件1 ---vuex-persistedstate

// 安装
// yarn add vuex-persistedstate
// 或
// npm install --save vuex-persistedstate


// 使用
// store.js
import Vuex from "vuex"
import createPersistedState from "vuex-persistedstate"
Vue.use(Vuex)

const store = new Vuex.Store({
  modules,
  getters,
  plugins: [
    // 持久化插件配置
    createPersistedState({
      // storage:存储位置,localStorage或sessionStorage或cookie
      // cookie 存储方式有区别,下面单独讲
      // 默认存储在localStorage中
      storage: window.sessionStorage,
      // 存储的 key 值,默认是vuex
      key: 'vueX',
      // 要存储的数据,render函数的参数是state对象
      render(state) {
        return { ...state }
        // 我这里直接把state中的全部数据解构存进去,
        // 也可以只存需要的数据,以key:value的形式
        // 如下
        // return {userName:state.userName}
      }
    })
  ]
})

再者可以手动实现....

posted @   奇迹会出现  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示