如何使用 Vuex的入门教程

目录
  • 前言
  • 一、基本概念
    • 初识vuex
  • 二、项目场景
  • 三、如何使用
    • 1、安装
    • 2、State初始值
    • 3、Getters修饰值
    • 4、Mutations修改值
    • 5、Actions异步修改值
  • 四、总结
  • 五、建议

前言

本人曾对 Vuex 作过详细介绍,但是今天去回顾的时候发现文章思路有些繁琐,不容易找到重点。于是,在下班前几分钟,我对其重新梳理了一遍。

tips:本文的案例均为Vue2版本。

一、基本概念

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

初识vuex

vuex有什么用?

比如, vue做了一个音乐app, 里面的播放组件, 这组件应该是在所有的页面都有用到的.

希望在所有的页面都能控制播放器的 暂停/播放, 或者说都可以选择是否 随便播放/单曲循环.

这就涉及到了多组件之间的传参,而且是非常复杂的传参.这时候使用vuex是合适的.

二、项目场景

如果你的项目里有很多页面(组件/视图),页面之间存在多级的嵌套关系,此时,如果这些页面都需要共享一个状态的时候,此时就会产生以下两个问题:

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

解决方案(初版):

  • 对于第一个问题,假如是多级嵌套关系,你可以使用父子组件传参进行解决,虽有些麻烦,但好在可以解决;对于兄弟组件或者关系更复杂组件之间,虽然可以通过各种各样的办法解决,可实在很不优雅,而且等项目做大了,代码量愈发巨大,实在令人心烦。
  • 对于第二个问题,你可以通过父子组件直接引用,或者通过事件来变更或者同步状态的多份拷贝,但是这种模式很脆弱,使得代码难以维护,而且同样会让代码量剧增。

思路:

  • 把各个组件都需要依赖的同一个状态抽取出来,全局统一管理。
  • 在这种模式下,任何组件都可以直接访问到这个状态,或者当状态发生改变时,所有的组件都相应更新。

此时,Vuex 就诞生了。 这就是它背后的基本思想,借鉴了 Flux、Redux。与其他模式不同的是,Vuex 是专门为 Vue 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。

三、如何使用

1、安装

进入项目,键入以下命令:

npm install vuex --save

2、State 初始值

在 src 路径下创建 store 文件夹,并在该文件夹下新增 index.js 文件:

import Vue from 'vue';
import Vuex from 'vuex';
 
Vue.use(Vuex);
 
const store = new Vuex.Store({
    state: {
        // 定义一个name,以供全局使用
        name: 'leo'
    }
});
 
export default store;

修改 main.js:

import Vue from 'vue';
import App from './App';
import store from './store';   // 引入我们前面导出的store对象
 
Vue.config.productionTip = false;
 
new Vue({
    el: '#app',
    store,   // 把store对象添加到vue实例上
    components: { App },
    template: '<App/>'
});

最后修改 App.vue:

<template>
    <div></div>
</template>
 
<script>
    export default {
        mounted() {
            // 使用this.$store.state.xxx可以直接访问到仓库中的状态
            console.log(this.$store.state.name);   // 'leo'
        }
    }
</script>

建议一:this.$store.state.xxx 放在计算属性中,这样可以让你的代码看起来更优雅一些。

export default {
    mounted() {
        console.log(this.getName);   // 'leo'
    },
    computed:{
        getName() {
            return this.$store.state.name;
        }
    }
}

建议二:每次都写 this.$store.state.xxx 让你感到厌烦,造成代码冗余,可以使用 mapState。

<script>
import { mapState } from 'vuex';   // 从vuex中导入mapState
export default {
    mounted() {
        console.log(this.name);   // 'leo'
    },
    computed: {
        ...mapState(['name'])   // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
    }
}
</script>

你甚至可以给它取别名:

...mapState({ userName: 'name' })   // 赋别名的话,这里接收对象,而不是数组

3、Getters 修饰值

设想一个场景,你已经将 store 中的 name 展示到页面上了,而且是很多页面都展示了,此时客户要求在每个 name 前都加上“hello”。

最容易想到的办法就是去每个用到 name 的页面一个一个加上“hello”,显然这种方式并不友好,原因如下:

第一,假如你在A、B、C三个页面都用到了 name,那么你要在这A、B、C三个页面都修改一遍,多个页面你就要加很多遍这个方法,造成代码冗余,很不好。

第二,假如下次客户让你把“hello”改成“greet”的时候,你又得把三个页面(甚至更多)都改一遍,这时候你是拿石头砸自己的脚。

吸取上面的教训,我们有一个新的思路:直接在 store 中对 name 进行一些操作或者加工,从源头解决问题!这时候,Getter 闪亮登场!

首先,在 store 对象中增加 getters 属性:

const store = new Vuex.Store({
    state: {
        name: 'leo'
    },
    // 在store对象中增加getters属性
    getters: {
        getMessage(state) {   // 获取修饰后的name,第一个参数state为必要参数,必须写在形参上
            return `hello ${state.name}`;
        }
    }
});

在组件中使用:

export default {
    mounted() {
        console.log(this.$store.state.name);
        console.log(this.$store.getters.getMessage);   // 注意不是$store.state了,而是$store.getters
    }
}

建议使用 mapGetters:

<script>
import { mapState, mapGetters } from 'vuex';
export default {
    mounted() {
        console.log(this.name);   // 'leo'
        console.log(this.getMessage);   // 'hello leo' 
    },
    computed: {
        ...mapState(['name']),
        ...mapGetters(['getMessage'])
    },
}
</script>

你也可以给它取别名:

...mapGetters({ greetMsg: 'getMessage' })   // 赋别名的话,这里接收对象,而不是数组

4、Mutations 修改值

说到修改值,有的人可能会想到这样写:

this.$store.state.xxx = XXX;

首先,这是一种错误的写法。为什么说是错误的写法?因为这个 store 仓库比较奇怪,你可以随便拿,但是你不能随便改,举个例子:

假如你打开朋友圈,看到你的好友发了条动态,但是动态里有个错别字,你要怎么办呢?你可以帮他改掉吗?当然不可以!我们只能通知他本人去修改,因为是别人的朋友圈,你是无权操作的,只有他自己才能操作。同理,在 Vuex 中,我们不能直接修改仓库里的值,必须用 Vuex 自带的方法去修改。这个时候,Mutation 闪亮登场!

首先,修改 store/index.js:

const store = new Vuex.Store({
    state: {
        name: 'leo',
        number: 0,
    },
    mutations: {   // 增加nutations属性
        setNumber(state) {   // 增加一个mutations的方法,方法的作用是让number从0变成5,state是必须默认参数
            state.number = 5;
        }
    }
});

然后,修改 App.vue:

<script>
export default {
    mounted() {
        console.log(this.$store.state.number);   // 旧值,0
        this.$store.commit('setNumber');
        console.log(this.$store.state.number);   // 新值,5
    },
}
</script>

如果我们想传动态参数怎么办?

首先,修改 store/index.js:

const store = new Vuex.Store({
    state: {
        name: 'leo',
        number: 0,
    },
    mutations: {
        setNumber(state, num) {   // 增加一个带参数的mutations方法
            state.number = num;
        },
    },
});

相应地,修改 App.vue:

<script>
export default {
    mounted() {
        console.log(this.$store.state.number);   // 旧值,0
        this.$store.commit('setNumber', 666);
        console.log(this.$store.state.number);   // 新值,666
    },
}
</script>

上面的这种传参的方式虽然可以达到目的,但是并不推荐。建议传递一个对象,看起来更美观,对象的名字你可以随意命名,一般命名为 payload:

mutations: {
    setNumber(state, payload) {   // 增加一个带参数的mutations方法,并且官方建议payload为一个对象
        state.number = payload.number;
    },
},

相应地,修改 App.vue:

<script>
export default {
    mounted() {
        console.log(this.$store.state.number);   // 旧值,0
        this.$store.commit('setNumber', { number: 666 });  // 调用的时候需要传递一个对象
        console.log(this.$store.state.number);   // 新值,666
    },
}
</script>

建议使用 mapMutations:

<script>
import { mapMutations } from 'vuex';
export default {
    mounted() {
        this.setNumber({ number: 666 });
    },
    methods: {   // 注意,mapMutations是解构到methods里面的,而不是计算属性了
        ...mapMutations(['setNumber'])
    }
}
</script>

你也可以给它取别名:

methods:{
    ...mapMutations({ changeNumber: 'setNumber' })   // 赋别名的话,这里接收对象,而不是数组
}

注意:Mutations 里面的函数必须是同步操作,不能包含异步操作。

Mutations 只能进行同步操作,所以,我们马上开始下一节,看看使用 Actions 进行异步操作的时候应该注意什么!

5、Actions 异步修改值

Vuex 不希望你将异步操作放在 Mutations 中,所以就给你设置了一个区域,让你进行异步操作,这就是 Actions。

首先,修改 store/index.js:

const store = new Vuex.Store({
    state: {
        name: 'leo',
        number: 0,
    },
    mutations: {
        setNumber(state, payload) {
            state.number = payload.number;
        },
    },
    actions: {   // 增加actions属性
        setNum(content) {   // 增加setNum方法,默认第一个参数是content,其值是复制的一份store
            return new Promise(resolve => {  // 模拟异步操作,1秒后修改number为666
                setTimeout(() => {
                    content.commit('setNumber', { number: 666 });
                    resolve();
                }, 1000);
            });
        }
    }
});

然后,修改 App.vue:

async mounted() {
    console.log(this.$store.state.number);   // 旧值,0
    await this.$store.dispatch('setNum');   // 等待异步操作完成
    console.log(this.$store.state.number);   // 新值,666
}

其实 action 就是去提交 mutation 的。异步操作都在 action 中消化了,最后再去提交 mutation。

当然,你也可以进行动态传参。

首先,修改 store/index.js:

actions: {
    setNum(content, payload) {   // 增加payload参数
        return new Promise(resolve => {
            setTimeout(() => {
                content.commit('setNumber', { number: payload.number });
                resolve();
            }, 1000);
        });
    },
}

相应地,修改 App.vue:

async mounted() {
    console.log(this.$store.state.number);   // 旧值,0
    await this.$store.dispatch('setNum', { number: 888 });
    console.log(this.$store.state.number);   // 新值,888
}

建议使用 mapActions:

<script>
import { mapActions } from 'vuex';
export default {
    methods: {
        ...mapActions(['setNum']),   // 解构到methods中
    },
    async mounted() {
        await this.setNum({ number: 888 });  // 直接调用即可
    }
}
</script>

你也可以给它取别名:

...mapActions({ changeNumber: 'setNum' })   // 赋别名的话,这里接收对象,而不是数组

tips:在 actions 里面,方法的形参可以直接将 commit 解构出来,方便后续操作。

actions: {
    setNum({ commit }) {   // 直接将content结构掉,解构出commit,下面就可以直接调用了
        return new Promise(resolve => {
            setTimeout(() => {
                commit('xxx');  // 直接调用
                resolve();
            }, 1000);
        });
    },
},

四、总结

下班前这几分钟,你知道了如何使用 Vuex。你会安装它,配置它,读取 state 的值,甚至修饰读(Getters),然后你会修改里面的值(Mutations),如果有异步操作并且需要修改 state,那你就要使用 Actions。

一张神奇的图。

五、建议

何时使用 Vuex ?

这个问题因人而异,如果你不需要开发大型的单页应用,此时你完全没有必要使用 Vuex,比如你的页面就两三个,使用 Vuex 后增加的文件比你现在的页面还要多,完全没这个必要。

假如你的项目达到了中大型应用的规模,此时你很可能会考虑如何更好地在组件外部对状态进行统一管理,甚至会分模块(Vuex 中的 module,不展开),它将会是一个不错的选择。

到此这篇关于如何使用 Vuex的入门教程的文章就介绍到这了,更多相关Vuex 入门教程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vuex 入门教程

    Vuex 是什么? 官方给出的解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 相信很多新选手看完这段话有种绝望的感觉.开始我也是这样的,后来我想到了一个比方! 比如某年级有5个小班,每个小班有25个同学,但是只有一个老师授课,假如5个小班就对应着5个组件,每个班的25个同学就相当于每个组件中的25条数据,这个老师就相当于 vuex ,老师讲的课就相当于每一条数据.要保证每个同学受到

  • Vuex 快速入门(简单易懂)

    一.vuex介绍  (1)vuex是什么? 1. 借鉴 了Flux.Redux. The Elm Architecture 2. 专为 Vue.js 设计 的状态管理模式 3. 集中式存储和管理应用程序中所有组件的状态 4. Vuex 也集成到 Vue 的官方调试工具 5. 一个 Vuex 应用的核心是 store(仓库,一个容器),store包含着你的应用中大部分的状态 (state). (2)什么情况下我应该使用 Vuex? 1. 不适用:小型简单应用,用 Vuex 是繁琐冗余的,更适合使用

  • 简单的三步vuex入门

    前言 之前几个项目中,都多多少少碰到一些组件之间需要通信的地方,而因为种种原因, event bus 的成本反而比vuex还高, 所以技术选型上选用了 vuex, 但是不知道为什么, 团队里的一些新人一听到vuex,就开始退缩了, 因为vuex 很难? 真的很难吗? 今天我们用简单的3步来证明一下,vuex有多简单. 纯属个人经验,难免有不正确的地方,如有发现,欢迎指正! 这是一个针对新手的入门级教程.入门级教程.入门级教程 第零步 新建一个vue项目,安装vuex,这里不做过多介绍,能点进来的

  • Vue.js实战之Vuex的入门教程

    前言 在 Vue.js 的项目中,如果项目结构简单, 父子组件之间的数据传递可以使用  props 或者 $emit 等方式,详细点击这篇文章查看. 但是如果是大型项目,很多时候都需要在子组件之间传递数据,使用之前的方式就不太方便.Vue 的状态管理工具 Vuex 完美的解决了这个问题. 一.安装并引入 Vuex 项目结构: 首先使用 npm 安装 Vuex cnpm install vuex -S 然后在 main.js 中引入 import Vue from 'vue' import App

  • 分分钟学会vue中vuex的应用(入门教程)

    vuex.js 状态(数据)管理 在vue中当我们管理数据的时候比较乱,我们要用到下面的这个库,vuex.js Vuex介绍 每一个Vuex应用的核心就是store(仓库),他是用来存储数据的 "store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state).Vuex 和单纯的全局对象有以下两点不同 1.Vuex 的状态存储是响应式的 2.你不能直接改变 store 中的状态 vuex有6个概念 Store(最基本的概念)(创库) State (数据) Getters(

  • vuex入门最详细整理

    如果你在使用 vue.js , 那么我想你可能会对 vue 组件之间的通信感到崩溃 . 我在使用基于 vue.js 2.0 的UI框架 ElementUI 开发网站的时候 , 就遇到了这种问题 : 一个页面有很多表单 , 我试图将表单写成一个单文件组件 , 但是表单 ( 子组件 ) 里的数据和页面 ( 父组件 ) 按钮交互的时候 , 它们之间的通讯很麻烦 : <!--父组件中引入子组件--> <template> <div> <a href="javas

  • vue基础入门之vuex安装与使用

    目录 1.什么是vuex 2.安装和引入 3.vuex的使用 4.流程介绍 5.mutation 6.getters过滤 7.Action--异步处理 8.Module 总结 本教程为入门教程,如有错误,请各位前端大佬指出. 1.什么是vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.详细介绍可以参照官网文档vuex.vuejs.org/zh/ 下面简单介绍vuex 2.安装和引入

  • Vuex入门到上手教程

    一.前言 当我们的应用遇到多个组件共享状态时,会需要多个组件依赖于同一状态.传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力.在搭建下面页面时,你可能会对 vue 组件之间的通信感到崩溃 ,特别是非父子组件之间通信.此时就应该使用vuex,轻松可以搞定组件间通信问题. 二.什么是Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.这里的关键在于集中式存储

  • Vuex简单入门

    1.Vuex是什么? 学院派:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式:集中存储和管理应用的所有组件状态. 理解:以上这4个词是我们理解的关键.状态:什么是状态,我们可以通俗的理解为数据.Vue只关心视图层,那么视图的状态如何来确定?我们知道是通过数据驱动,这里的状态管理可以简单理解为管理数据.集中存储:Vue只关心视图,那么我们需要一个仓库(Store)来存储数据,而且是所有的数据集中存储,视图和数据就可以分析.管理:除了存储,还可以管理数据,也就是计算.处理数据.所有组

  • 如何使用 Vuex的入门教程

    目录 前言 一.基本概念 初识vuex 二.项目场景 三.如何使用 1.安装 2.State初始值 3.Getters修饰值 4.Mutations修改值 5.Actions异步修改值 四.总结 五.建议 前言 本人曾对 Vuex 作过详细介绍,但是今天去回顾的时候发现文章思路有些繁琐,不容易找到重点.于是,在下班前几分钟,我对其重新梳理了一遍. tips:本文的案例均为Vue2版本. 一.基本概念 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组

  • vue3.0 CLI - 1 - npm 安装与初始化的入门教程

    node 开发环境请先自行准备 npm install -g @vue/cli 安装完成之后命令行则存在 vue 命令 vue -V 查看本地 vue 版本 vue -h 输出帮助 vue create <project-name> 进入工程文件夹,创建项目. 如:cd studyVue ( 进入工程文件夹 ) vue create config ( 创建 config 项目 ) 选择 default 配置项,下面没什么可介绍的,自行尝试. 下面介绍选择 manually select fea

  • Vue新的状态管理库Pinia入门教程

    目录 前沿 使用教程 1.安装 2.vue中引入 3.基本使用 4.也可以像vuex一样使用 为什么最近Pinia会火起来呢,主要在于Vue3推出来的时候,Vuex对于Vue3的组合式Api支持的不是特别好,也就是在这个时候Pinia出现了. 前沿 Vue官方推荐的状态管理库是Vuex,那为什么最近Pinia会火起来呢,主要在于Vue3推出来的时候,Vuex对于Vue3的组合式Api支持的不是特别好,也就是在这个时候Pinia出现了,最重要的是,Pinia不但支持Vue3,同时还支持Vue2,这

  • ABP(现代ASP.NET样板开发框架)系列之二、ABP入门教程详解

    ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate ABP 的由来 "DRY--避免重复

  • Python中强大的命令行库click入门教程

    前言 我们的游戏资源处理工具是Python实现的,功能包括csv解析,UI材质处理,动画资源解析.批处理,Androd&iOS自动打包等功能.该项目是由其他部门继承过来的,由于绝大部分代码不符合我们的业务需求,所以进行了大重构.删除了所有业务代码,仅保留了python代码框架.项目中命令行参数解析是自己实现的,极其不优雅,也忍了这么久.打算找时间用click重写.所以最近学习了click,下面本文的内容是click的入门教程,初学者们可以来一起学习学习. 官网镜像地址: http://click

  • 零基础易语言入门教程(六)之逻辑型命令

    逻辑型命令,就是非真即假的. 具体方法和步骤如下所示: 1.如果(): 属于逻辑型,不是真就是假,这种时间我们基本在编写程序时,会有两个选择方向,见下图所示: 2.如上图,如果命令属于逻辑型数据,且有两条输出方向,当我们在如果命令里填写的为真,那么我们的系统将会显示输出真的一个,反之则为假. 3.如果()命令在我们编写程序时属于常用命令,他在运行时我们需要给他一个条件,然后才能输出内容,有了条件我们在运行时给他一个输出方向即可, 以上所述是小编给大家介绍的零基础易语言入门教程(六)之逻辑型命令的

  • 零基础易语言入门教程(五)之逻辑型数据类型

    在上篇文章给大家介绍了零基础易语言入门教程(四)之数据类型,上篇针对数值到文本类型知识,今天给大家介绍下逻辑型数据. 具体方法和步骤如下所示: 1.逻辑型数据非真即假: 首先申请一个局部变量(A)类型为:逻辑型,编写代码为:A=1>2,那么输出的结果应为假,因等于1是赋值与1,然后代码中写道1大于2,所以这是假的,见下图所示: 2.关系运算符: 在上图大家需注意的是,A后面的等于号是赋值符号,而后面的≥,≠,<一些符号则是关系运算符. 关系运算符不是非要设置变量给其赋值才可以使用的,同样他可以

  • 零基础易语言入门教程(四)之数据类型

    我们一起了解下易语言的数据类型,跟我们现实生活是一样的,分为文本型和数值型,即是我们所说的文科生和理科生的区别. 参考文章:详解易语言中的数据类型 方法和步骤如下所示: 1.数值型(到数值命令): 使用该命令可将文本型等一类数据更改为数值型:我们来输入一行代码看看其作用: 2.到文本()命令: 我们先输入一行代码试试,见下图 3.小结: 每一行代码前后的数据类型必须转换为同一种,方可进行相连,相加,"+"在数据为文本型时是连接作用,数值型的跟数学里的符号一样. 以上所述是小编给大家介绍

随机推荐