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.rhkb.cn/news/207219.html

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

相关文章

嵌入式Linux:ARM驱动+QT应用+OpenCV人脸识别项目实现

一、前言&#xff1a; 这个项目主要分为两部分&#xff0c;客户端&#xff08;ARM板端&#xff09;负责利用OpenCV采集人脸数据&#xff0c;利用TCP将人脸数据发送给服务器&#xff0c;然后服务器根据人脸数据进行人脸识别&#xff0c;将识别后的结果返还给客户端&#xff0c;客…

Unity中Shader编译目标渲染器

文章目录 前言一、Unity在打包时&#xff0c;会把Shader编译成不同平台对应的代码我们在状态栏&#xff0c;可以看见我们目前所处于的目标平台 二、在Unity中&#xff0c;怎么指定目标平台1、#pragma only_renderers2、#pragma exclude_renderers 三、我们测试一下看看效果1、 …

C语言贪吃蛇(有详细注释)

这个贪吃蛇是在比特特训营里学到的&#xff0c;同时我还写了用EasyX图形库实现的图形化贪吃蛇&#xff0c;含有每个函数的实现以及游戏中各种细节的讲解&#xff0c;感兴趣的可以去看一看。 贪吃蛇小游戏 实现效果 以下就是源码&#xff0c;感兴趣的小伙伴可以cv自己玩一玩改…

Node.js+Express+Nodemon+Socket.IO构建Web实时通信

陈拓 2023/11/23-2023/11/27 1. 简介 Websocket WebSocket是一种在单个TCP连接上提供全双工通讯的协议。特别适合需要持续数据交换的服务&#xff0c;例如在线游戏、实时交易系统等。 Websocket与Ajax之间的区别 Ajax代表异步JavaScript和XML。它被用作一组Web开发技术&…

java实战(四):编写学生信息管理系统页面·

1.要求 编写程序 实现表格的输入和编辑功能。界面如下&#xff1a; 1、用户按插入键后&#xff0c;把学号、姓名和成绩插入到最后一行&#xff0c;序号显示当前的行号。 2、当用户选中表格的某一行时&#xff0c;按删除按钮&#xff0c;则这一行从表格中删除 3、编辑功能&am…

Linux常用命令——vi命令

文章目录 vi的工作模式常用快捷键提示和技巧结论 Linux环境下的vi编辑器不仅以其强大的功能著称&#xff0c;也因其快捷键而闻名。这些快捷键可以显著提高编辑效率&#xff0c;是每个使用vi的人必须掌握的。下面将扩展介绍vi的一些常用快捷键。 vi的工作模式 vi主要有两种模式…

Linux信号超详细剖析

预备知识&#xff1a; 一、信号产生(OS发给进程) 1、键盘组合键 Linux中&#xff0c;一次登录对应一个终端&#xff0c;bash/shell。且只允许一个进程是前台进程&#xff0c;默认就是bash/shell&#xff0c;其它都是后台进程。获取键盘输入的是前台进程。 Ctrlc: 向前台进程…

【android开发-01】android中toast的用法介绍

1&#xff0c;android中toast的作用 在Android开发中&#xff0c;Toast是一种用于向用户显示简短消息的轻量级对话框。它通常用于向用户提供一些即时的反馈信息&#xff0c;例如操作结果、提示或警告。 Toast的主要作用如下&#xff1a; 提供反馈&#xff1a;Toast可以在用户…

每日一练2023.12.1——帅到没朋友【PTA】

题目链接&#xff1a;L1-020 帅到没朋友 题目要求&#xff1a; 当芸芸众生忙着在朋友圈中发照片的时候&#xff0c;总有一些人因为太帅而没有朋友。本题就要求你找出那些帅到没有朋友的人。 输入格式&#xff1a; 输入第一行给出一个正整数N&#xff08;≤100&#xff09;&…

【MySQL】视图:简化查询

文章目录 create view … as创建视图更改或删除视图drop view 删除视图replace关键字&#xff1a;更改视图 可更新视图with check option子句&#xff1a;防止行被删除视图的其他优点简化查询减小数据库设计改动的影响使用视图限制基础表访问 create view … as创建视图 把常用…

分布式锁,分布式锁应该具备哪些条件,分布式锁的实现方式有:基于Zookeeper实现、Redis实现、数据库实现

文章目录 分布式锁0-1分布式锁--包含CAP理论模型概述分布式锁&#xff1a;分布式锁应该具备哪些条件&#xff1a;分布式锁的业务场景&#xff1a; 分布式锁的实现方式有&#xff1a;基于Zookeeper - 分布式锁实现思想优缺点基于Redis - 分布式锁实现思想实现思想的具体步骤&…

Linux驱动开发——网络设备驱动(实战篇)

目录 四、 网络设备驱动实例 五、DM9000 网络设备驱动代码分析 六、NAPI 七、习题 书接上回&#xff1a; Linux驱动开发——网络设备驱动&#xff08;理论篇&#xff09;-CSDN博客 &#xff08;没看过上面博客的同学&#xff0c;skb是linux对于网络套接字缓冲区的一个虚拟…

【微服务 SpringCloudAlibaba】实用篇 · Nacos配置中心

微服务&#xff08;6&#xff09; 文章目录 微服务&#xff08;6&#xff09;1. 统一配置管理1.1 在nacos中添加配置文件1.2 从微服务拉取配置 2. 配置热更新2.1 方式一2.2 方式二 3. 配置共享1&#xff09;添加一个环境共享配置2&#xff09;在user-service中读取共享配置3&am…

vue2 el-table 封装

vue2 el-table 封装 在 custom 文件夹下面创建 tableList.vue直接上代码&#xff08;代码比较多&#xff0c;复制可直接用&#xff09; <template><div class"mp-list"><el-tableref"multipleTable"class"mp-custom-table":dat…

Ubuntu18.4中安装wkhtmltopdf + Odoo16配置【二】

deepin Linux 安装wkhtmltopdf 1、先从官网的链接里下载linux对应的包 wkhtmltopdf/wkhtmltopdf 下载需要的版本&#xff0c;推荐版本&#xff0c;新测有效&#xff1a; wkhtmltox-0.12.4_linux-generic-amd64.tar.xz 2、解压下载的文件 解压后会有一个wkhtmltox文件夹 3…

【opencv】计算机视觉基础知识

目录 前言 1、什么是计算机视觉 2、图片处理基础操作 2.1 图片处理&#xff1a;读入图像 2.2 图片处理&#xff1a;显示图像 2.3 图片处理&#xff1a;图像保存 3、图像处理入门基础 3.1 图像成像原理介绍 3.2 图像分类 3.2.1 二值图像 3.2.2灰度图像 3.2.3彩色图像…

党建引领·和谐共建——赤岗街首届微型社区养老服务公益博览会开幕

服务咨询平台&#xff0c;让社区长者更便捷地了解到养老相关政策、信息。 本次活动由赤岗街公共卫生委员会、赤岗街道办事处、中国老龄事业发展基金会老年维权基金管理委员会主办&#xff0c;珠影社区居委会、广州市穗星社会工作服务中心、广州市盈泽信息科技有限公司承办&…

4/5G互操作 EPSFB讲解

今天我们来讲一下4/5G之间之间互操作&#xff0c;以及5G的EPSFB是基于什么实现的~ 目录 4/5G互操作 重选 切换 基于覆盖的切换 基于业务的切换 两个面试问题 想要加快4G切换5G的速度&#xff0c;调哪个参数怎么调高效&#xff1f; 想要减慢5G切换4G的速度调哪个参数怎…

项目计划阶段项目管理文档(风险管理、软件估计、立项、计划)

项目计划过程支撑文件&#xff1a; 1、风险和机会管理表 2、软件估计书模板 3、立项通知 4、项目计划书 软件开发全文档获取&#xff1a;点我获取 1、风险和机会管理表 2、软件估计书模板 3、立项通知 4、项目计划模板

Spring简单的存储和读取

前言 前面讲了spring的创建&#xff0c;现在说说关于Bean和五大类注解 一、Bean是什么&#xff1f; 在 Java 语⾔中对象也叫做 Bean&#xff0c;所以后⾯咱们再遇到对象就以 Bean 著称。这篇文章还是以spring创建为主。 二、存储对象 2.1 俩种存储方式 需要在 spring-conf…