0
点赞
收藏
分享

微信扫一扫

Vue 状态管理 Vuex

Vue 状态管理 Vuex

官网文档:​​https://vuex.vuejs.org/zh/​​

Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式,他采用集中式存储管理应用的所有组件的状态,并且以相应的规则保证状态以一种可以预测的方式发生改变。

Vuex 的简单理解

  • Vue 应用中的每一个组件在 data() 中封装自己的数据属性,而这些 data 属性是私有的,完全隔离的。
  • 如果我们希望多个组件都能读取到同一个状态数据属性,或者不同的组件的行为需要更新同一状态数据属性,这就需要一个将共享的状态数据属性进行集中式的管理。
  • 这就是 Vuex 状态管理所要解决的问题。

安装依赖

npm install --save vuex

Vue 状态管理 Vuex_模块化

使用Vuex

创建文件

在项目 src 文件夹下创建一个 store 文件夹,存储状态,将所有的状态存储到这个文件夹里面。在 store 文件夹下创建一个 index.js 文件。
Vue 状态管理 Vuex_数据属性_02

创建Vuex对象

在 index.js 文件中编写 Vuex 对象并导出。

在状态中存储一个 count 值为 1。

// 引入 vue 和 vuex
import Vue from 'vue'
import Vuex from 'vuex'

// 引入 Vuex 插件
Vue.use(Vuex)

// 创建一个仓库,用来存储对应的状态
const store = new Vuex.Store({
state: { // 存放状态(共享的属性)
count: 1
}
})

// 导出Vuex对象
export default store

将 Vuex 注册到 vue实例当中

在 main.js 文件中注册 Vuex。

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
// 导入 vuex,默认导入的是 ./store/index.js
import store from './store'

Vue.config.productionTip = false;

new Vue({
router,
store, // 注册
render: h => h(App)
}).$mount("#app");

获取状态 count 值

获取状态值得方式是 $store.state.状态名。

$store.state.xxx

在组件中使用:

<template>
<div class="home">
count:{{ $store.state.count }}
</div>
</template>

<script>

export default {
name: "Home",
};
</script>

Vue 状态管理 Vuex_数据属性_03

更改状态值

  1. 在 store 的 mutations 选项中定义方法,才可以改变状态值。
  2. 在通过 $store.commit("mutationName") 触发状态值的改变。

创建一个修改 count 值得方法,在 index.js 文件中,添加一个增加的方法,修改 state 对象中的 count 值。

mutations: {
// 增加的方法,改变state的状态值
increment(state) {
state.count ++
}
}

Vue 状态管理 Vuex_模块化_04

在组件中创建一个按钮,点击按钮,是的状态值 count 自增。

<template>
<div class="home">
<p>count:{{ $store.state.count }}</p>
<button @click="addCount">count 自加</button>
</div>
</template>

<script>
export default {
name: "Home",
methods: {
addCount() {
// 现获取状态值
console.log(this.$store.state.count);
// 修改 count 值
this.$store.commit('increment')
}
}
};
</script>

Vue 状态管理 Vuex_git_05
改变状态值 count 的方法就实现了。

在写一个自减哈,闲着也是闲着,做法和自加是一样的

index.js文件中:

mutations: {
// 增加的方法,改变state的状态值
increment(state) {
state.count ++
},
// 自减
decrement(state) {
state.count --
}
}

组件:

<template>
<div class="home">
<p>count:{{ $store.state.count }}</p>
<button @click="addCount">count 自加</button>
<button @click="decrement">count 自减</button>
</div>
</template>

<script>
export default {
name: "Home",
methods: {
addCount() {
// 现获取状态值
console.log(this.$store.state.count);
// 修改 count 值
this.$store.commit('increment')
},
decrement() {
// 现获取状态值
console.log(this.$store.state.count);
// 修改 count 值
this.$store.commit('decrement')
}
}
};
</script>

Vue 状态管理 Vuex_git_06
任意组件,都可以获取到状态值,数据是共享的,当一个地方改变了状态的值,所有的地方都可以获取到最新状态值。

提交载荷

就是向 $store.commit 中提交额外的参数,即 mutation 的载荷 (payload)。

例如:修改自加功能,增加的时候传进一个参数 n,是 count 加上传进来的 n。修改 index.js 文件自加方法:

mutations: {
// 增加的方法,改变state的状态值
increment(state, n) { // n 为载荷
state.count += n // state.count = state.count + n
},
// 自减
decrement(state) {
state.count --
}
}

Vue 状态管理 Vuex_数据属性_07

修改组件方法:

addCount() {
// 现获取状态值
console.log(this.$store.state.count);
// 修改 count 值
// this.$store.commit('increment')
this.$store.commit('increment', 10)
},

Vue 状态管理 Vuex_数据属性_08
Vue 状态管理 Vuex_数据属性_09

Action的作用和使用

Action 类似于 mutation,但不同点在于:

  1. Action 提交的是 mutation,而不是在组件中直接变更状态,通过他间接更新 state。
  2. 在组件中通过 this.$store.dispatch('actionName') 触发状态值间的改变。
  3. Action 也支持载荷。
  4. Action 可以包含任意异步操作。

修改 index.js 文件,添加 actions 。

// 引入 vue 和 vuex
import Vue from 'vue'
import Vuex from 'vuex'

// 引入 Vuex 插件
Vue.use(Vuex)

// 创建一个仓库,用来存储对应的状态
const store = new Vuex.Store({
state: { // 存放状态(共享的属性)
count: 1
},
mutations: {
// 增加的方法,改变state的状态值
increment(state, n) { // n 为载荷
state.count += n // state.count = state.count + n
},
// 自减
decrement(state) {
state.count--
}
},
actions: {
add(context) {
// 触发 mutations 中的 increment 来改变 state
context.commit('increment', 10)
}
}
})

// 导出Vuex对象
export default store

修改组件,点击自加按钮时候的逻辑:

addCount() {
// 现获取状态值
console.log(this.$store.state.count);
// 修改 count 值
// this.$store.commit('increment')
// this.$store.commit('increment', 10)
// 触发 action 修改 state
this.$store.dispatch('add')
},

Vue 状态管理 Vuex_git_10
action 也可以实现载荷

actions: {
add(context, n) {
// 触发 mutations 中的 increment 来改变 state
context.commit('increment', n)
}
}
addCount() {
// 现获取状态值
console.log(this.$store.state.count);
// 修改 count 值
// this.$store.commit('increment')
// this.$store.commit('increment', 10)
// 触发 action 修改 state
this.$store.dispatch('add', 10)
},

Vue 状态管理 Vuex_数据属性_11
效果一样!

action 还有其他的提交方式

比如修改减法

actions: {
add(context, n) {
// 触发 mutations 中的 increment 来改变 state
context.commit('increment', n)
},
// 参数是一个对象,commit就是提交,state就是状态对象,按需传入
decrement({commit,state}) {
console.log('actions.decrement.state.count ',state.count)
commit('decrement')
}
}

组件调用减法:

decrement() {
// 现获取状态值
// console.log(this.$store.state.count);
// 修改 count 值
// this.$store.commit('decrement')
this.$store.dispatch('decrement')
}

派生属性 getter

  1. 有时候哈,我们需要从 store 中的 state 中派生出一些状态。就比如说哈,基于上面的那个代码,增加一个 desc 属性,当那个 count 小于50的时候,desc 的值就是“吃饭饭”,大于等于50小于100,desc 的值就是 “睡觉觉”,当 count 的值大于100,desc 的值就是“打豆豆”。这个时候,我们就需要使用 getter 为我们解决问题了。
  2. getter 其实就是一个类似于计算属性(get)的对象。
  3. 组件中读取 $store.getter.xxx

修改 index.js 文件,增加 getters 选项:

getters: { // 定义派生属性
desc(state) { // 类似于计算属性的个玩意儿,会监听count值
// 这个state就是上面的state,他会自动的传进来
if(state.count < 50){
return '吃饭'
} else if (state.count < 100){
return '睡觉'
} else {
return '打豆豆'
}
}
}

Vue 状态管理 Vuex_git_12
修改组件,测试派生desc

<p>派生属性 desc 测试:{{ $store.getters.desc }}</p>

Vue 状态管理 Vuex_数据属性_13
效果就是下面的样子啦:
Vue 状态管理 Vuex_git_14

Vuex 模块化 Module 管理

随着状态值得增加,对状态值操作的增加,index.js 文件会变得越来约大,越来越臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module),每个模块有自己的 state、mutation、action、getter 等。

结构大体就是下面的样子:

const moduleA = {
state: {},
mutations: {},
actions: {},
getters: {}
}

const moduleB = {
state: {},
mutations: {},
actions: {}
}
const store = new Vuex.Store({
modules:{
a:modeuleA,
b:modulesB
}
})

store.state.a // modelA 的状态
store.state.b // modelB 的状态

模块化之前代码

index.js 文件

// 引入 vue 和 vuex
import Vue from 'vue'
import Vuex from 'vuex'

// 引入 Vuex 插件
Vue.use(Vuex)

// 将 home 相关的状态抽取为一个模块
const home = {
state: { // 存放状态(共享的属性)
count: 1
},
mutations: {
// 增加的方法,改变state的状态值
increment(state, n) { // n 为载荷
state.count += n // state.count = state.count + n
},
// 自减
decrement(state) {
state.count--
}
},
actions: {
add(context, n) {
// 触发 mutations 中的 increment 来改变 state
context.commit('increment', n)
},
// 参数是一个对象,commit就是提交,state就是状态对象
decrement({commit,state}) {
console.log('actions.decrement.state.count ',state.count)
commit('decrement')
}
},
getters: { // 定义派生属性
desc(state) { // 类似于计算属性的个玩意儿,会监听count值
// 这个state就是上面的state,他会自动的传进来
if(state.count < 50){
return '吃饭'
} else if (state.count < 100){
return '睡觉'
} else {
return '打豆豆'
}
}
}
}

// 将 goods 相关的状态抽取为一个模块
const goods = {
state: {},
mutations: {},
actions: {},
getters: {}
}

// 创建一个仓库,用来存储对应的状态
const store = new Vuex.Store({
modules: {
home, // home: home
goods,
}
})

// 导出Vuex对象
export default store

组件代码

<template>
<div class="home">
<!-- <p>count:{{ $store.state.count }}</p> --> <!-- 模块话之前 -->
<p>count:{{ $store.state.home.count }}</p> <!-- 模块话之后 -->
<button @click="addCount">count 自加</button>
<button @click="decrement">count 自减</button>
<p>派生属性 desc 测试:{{ $store.getters.desc }}</p>
</div>
</template>

<script>
export default {
name: "Home",
methods: {
addCount() {
// 现获取状态值
// console.log(this.$store.state.count); // 模块化钱前
console.log(this.$store.state.home.count); // 模块化后
// 修改 count 值
// this.$store.commit('increment')
// this.$store.commit('increment', 10)
// 触发 action 修改 state
this.$store.dispatch('add', 10)
},
decrement() {
// 现获取状态值
// console.log(this.$store.state.count);
// 修改 count 值
// this.$store.commit('decrement')
this.$store.dispatch('decrement')
}
}
};
</script>

Vue 状态管理 Vuex_git_15
一样的效果!完美~!

基于 Vuex 标准项目结构重构项目

如果所有的状态都写在一个 js 中,这个 js 必定会很臃肿,Vuex 并不限制你的代码结构。所以最好把每一部分都单独抽成一个 js 文件。

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:

  1. 应用层级的状态应该集中到单个 store 对象中。
  2. 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
  3. 异步逻辑都应该封装到 action 里面。

只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。

对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
Vue 状态管理 Vuex_git_16

注意! Vuex 的状态值在所有组件共享,在路由切换的时候状态值会得到保存,但是!在刷新整个页面之后,状态值会重置,这个是后如果想保留状态值,能且只能与 localStorage 进行配合。

【相关代码:​​https://gitee.com/wjw1014/vue_learning_vuex​​】

【版权声明】本博文著作权归作者所有,任何形式的转载都请联系作者获取授权并注明出处!

【重要说明】本文为本人的学习记录,论点和观点仅代表个人而不代表当时技术的真理,目的是自我学习和有幸成为可以向他人分享的经验,因此有错误会虚心接受改正,但不代表此刻博文无误!

【Gitee地址】秦浩铖:​​https://gitee.com/wjw1014​​


举报

相关推荐

0 条评论