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
通过 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
中的状态进行修改,虽然看起来有些繁琐,但是方便集中监控数据的变化,当中有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
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>
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}
}
})
]
})
再者可以手动实现....
标签:Vue,vuex,name,Vuex,state,上手,快速,store From: https://www.cnblogs.com/dutianyu/p/18134848