VueX简单又详细的解读,看了就会用

news2024/11/15 7:38:38

一、VueX是什么

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

二、为什么要用VueX

        “单向数据流”理念的简单示意:

         当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

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

        对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

        因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!

        通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。

VueX由此诞生:

 三、VueX的五大模块

(一)State:单一状态树

        Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。

        简单来说就是该项目中的所有状态都放在State中。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    // 全局个人数据
    userInfo:{},
    isLogin:true,
    loading:false,
    tabActive:0
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

        在别的页面使用时的获取方式

1.直接从store实例取值

         main.js中,把store注册在根实例下

import store from './store'
    (1)在其他页面js中可使用this.$stroe.state.属性直接取值
export default {
  computed: {
    testNum() {
      return this.$store.state.testNum;
    }
  }
};

        (2)在其他页面的html中书写为$stroe.state.属性

<div class="box" v-id="$store.state.isLogin">
    <MySelfHeader></MySelfHeader>
    <MySelfBody></MySelfBody>
</div>

2.mapState 辅助函数

        当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性.

    先引入   import {mapState} from "vuex";
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}

        当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

(二)Getter

        有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

         Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。

         Getter 接受 state 作为其第一个参数:

const store = createStore({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos (state) {
      return state.todos.filter(todo => todo.done)
    }
  }
})

在别的页面的获取方式:

        Js中:this.$store.getters.方法/属性

        html中:$store.getters.方法/属性

(三)Mutation

        更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

const store = createStore({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})

         你不能直接调用一个 mutation 处理函数。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation 处理函数,你需要以相应的 type 调用 store.commit 方法:

store.commit('increment')

提交载荷(Payload)

        你可以向 store.commit 传入额外的参数,即 mutation 的载荷(payload)

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

注意:Mutation 必须是同步函数,不能再Mutation中进行异步操作

***在组件中提交 Mutation***

        你可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

重点:Mutation中的方法要通过commit来调用

(四)Action

        某些情况我们希望在vuex中进行一些异步操作,比如网络请求,必然是异步的,那这个时候就需要用actions了。

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

        Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

分发 Action

        Action 通过 store.dispatch 方法触发:

store.dispatch('increment')

        乍一眼看上去感觉多此一举,我们直接分发 mutation 岂不更方便?实际上并非如此,还记得 mutation 必须同步执行这个限制么?Action 就不受约束!我们可以在 action 内部执行异步操作:

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

        Actions 支持同样的载荷方式和对象方式进行分发:

// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

****在组件中分发 Action***

        你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

(五)Module

        由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

        为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

四、VueX的源码

let Vue;
//定义一个Store类
class Store {
    constructor () {
        this._vm = new Vue({
            data: {
                $$state: this.state
            }
        })
    }

    commit (type, payload, _options) {
        const entry = this._mutations[type];
        entry.forEach(function commitIterator (handler) {
            handler(payload);
        });
    }

    dispatch (type, payload) {
        const entry = this._actions[type];
        return entry.length > 1
        ? Promise.all(entry.map(handler => handler(payload)))
        : entry[0](payload);
    }
}
//保证 vm 中都可以访问 store 对象
function vuexInit () {
    const options = this.$options;
    if (options.store) {
        this.$store = options.store;
    } else {
        this.$store = options.parent.$store;
    }
}
//Vue.js 提供了一个 Vue.use 的方法来安装插件,内部会调用插件提供的 install 方法。所以我们的插件需要提供一个 install 方法来安装。
export default install (_Vue) {
    
    Vue.mixin({ beforeCreate: vuexInit });
    Vue = _Vue;
}

        更多详情请跳转官网——

Vuex 是什么? | Vuex (vuejs.org)icon-default.png?t=M85Bhttps://vuex.vuejs.org/zh/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60027.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis缓存

一.简介 缓存就是数据交换的缓冲区&#xff08;称作Cache [ kʃ ] &#xff09;&#xff0c;是存贮数据的临时地方&#xff0c;一般读写性能较高 二.添加Redis缓存 三.缓存更新策略 1.主动更新策略 Cache Aside Pattern(推荐) 需要调用者自己编码&#xff0c;但可控性高 Re…

SimSiam-Exploring Simple Siamese Pepresentation Learning

SimSiam Abstract 模型坍塌&#xff0c;在siamese中主要是输入数据经过卷积激活后收敛到同一个常数上&#xff0c;导致无论输入什么图像&#xff0c;输出结果都能相同。 而He提出的simple Siamese networks在没有采用之前的避免模型坍塌那些方法&#xff1a; 使用负样本lar…

K_A08_003 基于 STM32等单片机驱动L9110模块按键控制直流电机正反转加减速启停

目录 一、资源说明 二、基本参数 1、参数 2、引脚说明 三、驱动说明 L9110模块驱动时序 对应程序: PWM信号 四、部分代码说明 接线说明 1、STC89C52RCL9110模块 2、STM32F103C8T6L9110模块 五、基础知识学习与相关资料下载 六、视频效果展示与程序资料获取 七、项目主要…

【Android工具】群晖安卓客户端基础套件:Drive、video、Photos和DS video安卓TV客户端...

微信关注公众号 “DLGG创客DIY”设为“星标”&#xff0c;重磅干货&#xff0c;第一时间送达。最近终于把all in one搞起来了&#xff0c;all in one就是把一堆功能一堆软件装一台主机里。。all in one&#xff08;以后简称AIO&#xff09;相关内容回头慢慢聊。今天先聊聊群晖&…

从一个demo说elf文件

本文的demo是在linux环境下编译解析的&#xff0c;cpu是x86-64 首先我们先写一个功能简单的demo-SimpleSection.c。这个demo中有一个func1函数用来打印数据&#xff0c;一个已经初始化的全局变量global_init_var和未初始化的全局变量global_uninit_var&#xff0c;一个已初始化…

使用TS 封装 自定义hooks,实现不一样的 CRUD

文章目录使用TS 封装 自定义hooks&#xff0c;实现不一样的 CRUD自定义 hooks文件结构type.tsuseDelData.ts使用useFetchList.ts使用useInsert.ts使用部分的接口方法使用TS 封装 自定义hooks&#xff0c;实现不一样的 CRUD 这一篇主要是记录 查缺补漏&#xff0c;提升自己的 强…

三、内存管理 (一)存储器管理

目录 1.1程序运行的基本过程 1.1.1 编辑、编译、链接、装入 1.1.2链接的三种方式 1.1.3装入的三种方式 1.2内存管理基本概念 1.2.1内存保护 1.2.2内存空间扩充 1.2.3地址转换功能 1.2.4内存空间的分配与回收 1.2.4.1连续分配管理方式 1.2.4.1.1单一连续分配 1.2.4.1…

Http协议和Https协议

Http是不安全的&#xff0c;你的数据容易被黑客拦截&#xff0c;篡改&#xff0c;攻击 https要求对数据加密&#xff08;不能明文传输&#xff09;, 用抓包工具抓http请求&#xff0c;抓出来的都是明文的&#xff0c;你能看得懂的&#xff0c;抓https请求&#xff0c;抓出来的…

网站域名被QQ拦截提示:当前网页非官方页面拦截的解决办法

今天网友提醒&#xff0c;星空站长网的链接被QQ屏蔽拦截了。提示&#xff1a;当前页面非官方页面&#xff0c;请复制到浏览器打开。 如图&#xff1a; 原因&#xff1a;这是因为QQ方面的诈骗信息特别多&#xff0c;所以腾讯官方索性就直接屏蔽了所有的外部链接。让站长们通过申…

Python源码剖析笔记1-整数对象PyIntObject

1、PyIntObject 对象 [intobject.h] typedef struct {PyObject_HEADlong ob_ival; } PyIntObjectPyIntObject是一个不可变&#xff08;immutable&#xff09;对象。Python内部也大量的使用整数对象&#xff0c;我们在自己的代码中也会有大量的创建销毁整型对象的操作&#xff…

SVM 用于将数据分类为两分类或多分类(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

CMake中install的使用

CMake中的install命令用于指定安装时要运行的规则&#xff0c;其格式如下&#xff1a; install(TARGETS targets... [EXPORT <export-name>][RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>][[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDL…

基于单片机的电压电流表设计

原理图&#xff1a; 部分程序&#xff1a; #include "stc15.h" #include "delay.h" #include "timer.h" #include "TM7707.h" #include "LCD1602.h" #include "eeprom.h" #include "stdio.h" #include…

【数学】双根号求值域问题

∣双根号求值域问题NightguardSeries.∣\begin{vmatrix}\Huge{\textsf{ 双根号求值域问题 }}\\\texttt{ Nightguard Series. }\end{vmatrix}∣∣∣∣∣​ 双根号求值域问题 Nightguard Series. ​∣∣∣∣∣​ 求 f(x)3x−63−xf(x)\sqrt{3x-6}\sqrt{3-x}f(x)3x−6​3−x​ 的…

开发工具——gdb

开发工具gdb gdb在Linux下负责程序的调试。 gdb相较于vs2019的调试&#xff0c;是不方便的。图形化界面调试确实是一种进步的现象。 先编写一个简单的程序&#xff0c;如果不支持在for循环中定义变量&#xff0c;要在编译指令后面加上-stdc99选项。 要编译的文件和要生成的文…

Spring 源码编译

Spring 源码编译&#xff0c;一定要选好版本&#xff01;&#xff01;&#xff01; Spring 源码编译&#xff0c;一定要选好版本&#xff01;&#xff01;&#xff01; Spring 源码编译&#xff0c;一定要选好版本&#xff01;&#xff01;&#xff01; 重要的事说三遍。 Spri…

MYSQL用函数请三思

背景&#xff1a;最近公司有个同事遇到个需求需要用到mysql sleep函数&#xff0c;但结果却大出意料. 测试如下&#xff1a; 表&#xff1a; CREATE TABLE test_sleep ( id int NOT NULL AUTO_INCREMENT, a int NOT NULL, b int NOT NULL, PRIMARY KEY (id), KEY a (a) ) ENGIN…

电子学会2021年3月青少年软件编程(图形化)等级考试试卷(一级)答案解析

青少年软件编程&#xff08;图形化&#xff09;等级考试试卷&#xff08;一级&#xff09; 分数&#xff1a;100.00 题数&#xff1a;37 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 1. 花花幼儿园有三个班。根据下面三句话&…

CentosLinux 7 字符安装教程

打开VMware虚拟机,点击文件 — 新建虚拟机选项。在弹出的对话框中选择自定义(高级)选项。单机下一步。 以下步骤根据自己的所需自行配置

[附源码]Python计算机毕业设计Django酒店在线预约咨询小程序

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…