vue.js ——Vuex

基本概念

vue进行开发过程中有没有遇到这样一种场景,就是有些时候一些数据是一种通用的共享数据(比如登录信息),那么这类数据在各个组件模块中可能都会用到,如果每个组件中都去后台重新获取那么势必会造成性能浪费,为了解决这一问题一个新的状态管理工具 - vuex就应运而生
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

什么是“状态管理模式”?

这个状态自管理应用包含以下几个部分:

  • 状态,驱动应用的数据源;
  • 视图,以声明方式将状态映射到视图;
  • 操作,响应在视图上的用户输入导致的状态变化。

安装方式

CDN引用

https://unpkg.com/vuex@4

Unpkg.com 提供了基于 npm 的 CDN 链接。以上的链接会一直指向npm 上发布的最新版本。
您也可以通过 https://unpkg.com/vuex@4.0.0/dist/vuex.global.js 这样的方式指定特定的版本。

Npm
npm install vuex@next --save
Yarn
yarn add vuex@next --save

核心概念

State

  • 单一状态树
    Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
  • 在 Vue 组件中获得 Vuex 状态
    由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
const Counter = {template: `<div>{{ count }}</div>`,computed: {count () {return store.state.count}}}

每当store.state.count变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM
Vuex 通过 Vue 的插件系统将 store 实例从根组件中“注入”到所有的子组件里。且子组件能通过this.$store访问到。让我们更新下Counter的实现:

const Counter = {template: `<div>{{ count }}</div>`,computed: {count () {return this.$store.state.count}}}
  • mapState 辅助函数
    当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。
    为了解决这个问题,我们可以使用 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}})}
  • 对象展开运算符
    mapState函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给computed属性。但是自从有了对象展开运算符【…】,我们可以极大地简化写法:
computed: {localComputed () { /* ... */ },// 使用对象展开运算符将此对象混入到外部对象中...mapState({// ...})}

对象展开运算符
var obj = {a:1,b:2}
var obj1 = {c:3,d:4}
var obj2 ={…obj,…obj1}
var obj3 = {…obj,a:8,w:66}
var obj4 ={…obj,a:8,w:66,…obj1}
console.log(obj); //{a: 1, b: 2}
console.log(obj1); //{c: 3, d: 4}
console.log(obj2); //{a: 1, b: 2,c: 3, d: 4}
console.log(obj3); //{a: 8, b: 2, w: 66}
console.log(obj4); //{a: 8, b: 2, w: 66, c: 3, d: 4}

Getter

我们需要从 store 中的 state 中派生出一些状态,如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它——无论哪种方式都不是很理想。
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
从 Vue 3.0 开始,getter 的结果不再像计算属性一样会被缓存起来
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)}}})
  • 通过属性访问
    Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值:
store.getters.doneTodos 

Getter 也可以接受其他 getter 作为第二个参数

getters: {// ...doneTodosCount (state, getters) {return getters.doneTodos.length}}
  • 通过方法访问
    你也可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时非常有用。
getters: {getTodoById: (state) => (id) => {return state.todos.find(todo => todo.id === id)}}
store.getters.getTodoById(2)

getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。

  • mapGetters 辅助函数
    mapGetters辅助函数仅仅是将store中的getter映射到局部计算属性
import { mapGetters } from 'vuex'
export default {// ...computed: {// 使用对象展开运算符将 getter 混入 computed 对象中...mapGetters(['doneTodosCount','anotherGetter',// ...])}}

Mutation

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

const store = createStore({state: {count: 1},mutations: {increment (state) {// 变更状态state.count++}}})
  • 提交载荷(Payload)
    你可以向 store.commit 传入额外的参数,即 mutation 的载荷(payload):
mutations: {increment (state, n) {state.count += n}}
store.commit('increment', 10)
  • 对象风格的提交方式
    提交 mutation 的另一种方式是直接使用包含 type 属性的对象:
store.commit({type: 'increment',amount: 10})

当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此处理函数保持不变:

mutations: {increment (state, payload) {state.count += payload.amount}}
  • Mutation 必须是同步函数
    一条重要的原则就是要记住 mutation 必须是同步函数

Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
  • 分发 Action
    Action 通过 store.dispatch 方法触发:
store.dispatch('increment')
actions: {incrementAsync ({ commit }) {setTimeout(() => {commit('increment')}, 1000)}}
  • 在组件中分发 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 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:

  • 应用层级的状态应该集中到单个 store 对象中。
  • 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
  • 异步逻辑都应该封装到 action 里面。
    只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。
    对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
    在这里插入图片描述

热重载

使用 webpack 的 Hot Module Replacement API,Vuex 支持在开发过程中热重载 mutation、module、action 和 getter。你也可以在 Browserify 中使用 browserify-hmr 插件。
对于 mutation 和模块,你需要使用 store.hotUpdate() 方法:

// store.js
import { createStore } from 'vuex'
import mutations from './mutations'
import moduleA from './modules/a'
const state = { ... }
const store = createStore({state,mutations,modules: {a: moduleA}})
if (module.hot) {// 使 action 和 mutation 成为可热重载模块module.hot.accept(['./mutations', './modules/a'], () => {// 获取更新后的模块// 因为 babel 6 的模块编译格式问题,这里需要加上 `.default`const newMutations = require('./mutations').defaultconst newModuleA = require('./modules/a').default// 加载新模块store.hotUpdate({mutations: newMutations,modules: {a: newModuleA}})})}

动态模块热重载
如果你仅使用模块,你可以使用 require.context 来动态地加载或热重载所有的模块。

// store.js
import { createStore } from 'vuex'
// 加载所有模块。function loadModules() {const context = require.context("./modules", false, /([a-z_]+)\.js$/i)const modules = context.keys().map((key) => ({ key, name: key.match(/([a-z_]+)\.js$/i)[1] })).reduce((modules, { key, name }) => ({...modules,[name]: context(key).default}),{})return { context, modules }}
const { context, modules } = loadModules()
const store = new createStore({modules})
if (module.hot) {// 在任何模块发生改变时进行热重载。module.hot.accept(context.id, () => {const { modules } = loadModules()store.hotUpdate({modules})})}

组合式api

可以通过调用 useStore 函数,来在 setup 钩子函数中访问 store。这与在组件中使用选项式 API 访问 this.$store 是等效的。

import { useStore } from 'vuex'
export default {setup () {const store = useStore()}}

访问 State 和 Getter
为了访问 state 和 getter,需要创建 computed 引用以保留响应性,这与在选项式 API 中创建计算属性等效。

import { computed } from 'vue'import { useStore } from 'vuex'
export default {setup () {const store = useStore()return {// 在 computed 函数中访问 statecount: computed(() => store.state.count),// 在 computed 函数中访问 getterdouble: computed(() => store.getters.double)}}}

访问 Mutation 和 Action
要使用 mutation 和 action 时,只需要在 setup 钩子函数中调用 commit 和 dispatch 函数。

import { useStore } from 'vuex'
export default {setup () {const store = useStore()return {// 使用 mutationincrement: () => store.commit('increment'),// 使用 actionasyncIncrement: () => store.dispatch('asyncIncrement')}}}

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

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

相关文章

websocket 消息包粗解

最近在搞websocket解析&#xff0c;记录一下: 原始字符串 &#xfffd;~&#xfffd;{"t":"d","d":{"b":{"p":"comds/comdssqmosm7k","d":{"comdss":{"cmdn":"success",…

免费使用GPT的网站

登录ChatGPT系统 登录ChatGPT系统 登录ChatGPT系统

ArkTs变量类型、数据类型基础语法

可以参考官网学习路径学习HarmonyOS第一课|应用开发视频教程学习|HarmonyOS应用开发官网 ArkTS是华为自研的开发语言。它在TypeScript&#xff08;简称TS&#xff09;的基础上&#xff0c;匹配ArkUI框架&#xff0c;扩展了声明式UI、状态管理等相应的能力&#xff0c;让开发者以…

浅谈安科瑞ASJ继电器在菲律宾矿厂的应用

摘要&#xff1a;对电气线路进行接地故障保护&#xff0c;方式接地故障电流引起的设备和电气火灾事故越来越成为日常所需。针对用户侧主要的用能节点&#xff0c;设计安装剩余电流继电器&#xff0c;实时监控各用能回路的剩余电流状态。通过实时监控用能以及相关电力参数、提高…

ESP32-Web-Server编程- 通过 Highcharts 创建图表(Chart)实时显示设备信息

ESP32-Web-Server编程- 通过 Highcharts 创建图表&#xff08;Chart&#xff09;实时显示设备信息 概述 上节讲述了通过 Server-Sent Events&#xff08;以下简称 SSE&#xff09; 实现在网页实时更新 ESP32 Web 服务器的传感器数据&#xff0c;并通过表格显示传感器的数据。…

操作系统--中断异常

操作系统第一章易错总结 1.操作系统的功能 ⭐ 编译器是操作系统的上层软件&#xff0c;不是操作系统需要提供的功能。 ⭐注意&#xff1a; 1.批处理的主要缺点是缺乏交互性 2.输入/输出指令需要中断操作&#xff0c;中断必须在核心态下执行 3.多道性是为了提高系统利用率和…

【Spring MVC】Filter 过滤器异常处理 HandlerExceptionResolver 分析

文章目录 前言版本说明测试 Demo1、自定义过滤器 DemoFilter2、自定义业务异常 ServiceException3、自定义异常处理类 DemoExceptionHandler4、DemoController5、请求测试 问题分析1、日志打印记录2、Debug 方法 解决方案1、修改自定义过滤器2、请求测试 解决方案分析1、日志打…

提升技能素养,AMCAP做出合适的决策

近年来&#xff0c;智能配置投资与理财逐渐受到关注并走俏。这是一种简单快捷的智慧化理财方式&#xff0c;通过将个人和家族的闲置资金投入到低风险高流动性的产品中。 国际财富管理投资机构AMCAP集团金融分析师表示&#xff1a;智能配置投资与理财之所以持续走俏&#xff0c…

6.3 Windows驱动开发:内核枚举IoTimer定时器

内核I/O定时器&#xff08;Kernel I/O Timer&#xff09;是Windows内核中的一个对象&#xff0c;它允许内核或驱动程序设置一个定时器&#xff0c;以便在指定的时间间隔内调用一个回调函数。通常&#xff0c;内核I/O定时器用于周期性地执行某个任务&#xff0c;例如检查驱动程序…

在Linux上安装KVM虚拟机

一、搭建KVM环境 KVM&#xff08;Kernel-based Virtual Machine&#xff09;是一个基于内核的系统虚拟化模块&#xff0c;从Linux内核版本2.6.20开始&#xff0c;各大Linux发行版就已经将其集成于发行版中。KVM与Xen等虚拟化相比&#xff0c;需要硬件支持的完全虚拟化。KVM由内…

使用 kubeadm 部署 Kubernetes 集群(一)linux环境准备

一、 初始化集群环境 准备三台 rocky8.8 操作系统的 linux 机器。每台机器配置&#xff1a;4VCPU/4G 内存/60G 硬盘 环境说明&#xff1a; IP 主机名 角色 内存 cpu 192.168.1.63 xuegod63 master 4G 4vCPU 192.168.1.64 xuegod64 worker 4G 4vCPU 192.168.1.62 xuegod62 work…

Python 异常处理(try except)

文章目录 1 概述1.1 异常示例 2 异常处理2.1 捕获异常 try except2.2 抛出异常 raise 3 异常类型3.1 内置异常3.2 自定义异常 1 概述 1.1 异常示例 异常&#xff1a;程序执行中出现错误&#xff0c;若不处理&#xff0c;则程序终止 示例代码&#xff1a; v 6 / 0 # 除数不…

基于matlab的图像去噪算法设计与实现

摘 要 随着我们生活水平的提高&#xff0c;科技产品飞速更新换代&#xff0c;在信息传输中&#xff0c;图像传输所占的比重越来越大。但自然噪声会在图像传输时干扰其传输过程&#xff0c;甚至会使图片不能表达其原来的意义。去噪处理就是为了去除图像中的噪声&#xff0c;从而…

【数据清洗 | 数据规约】数据类别型数据 编码最佳实践,确定不来看看?

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

tex2D使用学习

1. 背景&#xff1a; 项目中使用到了纹理进行插值的加速&#xff0c;因此记录一些自己在学习tex2D的一些过程 2. 代码&#xff1a; #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <assert.h> #include <stdio.h>…

Maven的安装和使用

Maven是一个基于项目对象模型&#xff08;POM&#xff09;&#xff0c;可以管理项目构建、依赖管理、项目报告等的工具&#xff0c;使构建Java项目更容易。可以说Maven是一个项目管理和构建工具&#xff0c;它可以从管理项目的角度出发&#xff0c;将开发过程中的需求纳入进来&…

FFmpeg架构全面分析

一、简介 它的官网为&#xff1a;https://ffmpeg.org/&#xff0c;由Fabrice Bellard&#xff08;法国著名程序员Born in 1972&#xff09;于2000年发起创建的开源项目。该人是个牛人&#xff0c;在很多领域都有很大的贡献。 FFmpeg是多媒体领域的万能工具。只要涉及音视频领…

软文推广如何自然融入品牌?媒介盒子有妙招

软文推广作为一种柔性推广方式&#xff0c;能将品牌信息融入到用户日常浏览的内容中&#xff0c;让用户不知不觉接触品牌&#xff0c;从而产生好感&#xff0c;这种方式既可以避免广告带来的反感&#xff0c;又可以提高广告的有效性。那么在推广中应该如何自然融入品牌信息呢&a…

leetCode 78.子集 + 回溯算法 + 图解

给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2],[1,2],[3],[1…

11月30日作业

设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数 #include <iostream>using namespace std;class …