【富文本编辑器实战】03 Vuex 的配置编写

Vuex 的配置编写

目录

  • Vuex 的配置编写
    • Vuex 是什么?
    • 什么是“状态管理模式”?
    • 什么情况下我应该使用 Vuex?
    • 安装 Vuex
    • 开始使用 Vuex
      • Action 文件
      • Mutations-types 文件
      • Mutation 文件
      • Index

Vuex 是什么?

这里我们来看看官方网站是如何介绍 Vuex 的:

提示

这是与 Vue 3 匹配的 Vuex 4 的文档。如果您在找与 Vue 2 匹配的 Vuex 3 的文档,请在这里查看。

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

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

让我们从一个简单的 Vue 计数应用开始:

const Counter = {// 状态data () {return {count: 0}},// 视图template: `<div>{{ count }}</div>`,// 操作methods: {increment () {this.count++}}
}createApp(Counter).mount('#app')

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

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

以下是一个表示“单向数据流”理念的简单示意:

在这里插入图片描述

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

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

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

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

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

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

如果你想交互式地学习 Vuex,可以看这个 Scrimba 上的 Vuex 课程,它将录屏和代码试验场混合在了一起,你可以随时暂停并尝试。

在这里插入图片描述

什么情况下我应该使用 Vuex?

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。

如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。引用 Redux 的作者 Dan Abramov 的话说就是:

Flux 架构就像眼镜:您自会知道什么时候需要它。

安装 Vuex

我们可以使用下面的方式来安装 Vuex:

使用 npm 包管理器安装:

npm install vuex@next --save

使用 Yarn 包管理器安装:

yarn add vuex@next --save

在这里我们选择 npm 安装:

在这里插入图片描述

开始使用 Vuex

安装完成之后,就可以开始使用 vuex 了。我们先在 /src 中创建 /store 文件夹,并创建 js 文件 action.js , index.js , mutations-types.js , mutations.js。如下图所示:

在这里插入图片描述

新建目录结构如上图。从文件名可以看出其对应的作用,下面我们来编写对应的代码。

Action 文件

即图中的 action.js 文件。里面存放着各个 action,每个 action 都对应一个 mutation,下面是 action.js 文件的完整代码:

export default {// 展示下拉框showDropList({ commit }, data) {commit("SHOW_DROP_LIST", data);},// 更新编辑区内容updateContent({ commit }, data) {commit("UPDATE_CONTENT", data);},// 更新选择的值updateSelectValue({ commit }, data) {commit("UPDATE_SELECTED_VALUE", data);},// 更新菜单状态updateMenuStatus({ commit }, data) {commit("UPDATE_MENU_STATUS", data);},// 执行命令execCommand({ commit }, data) {commit("EXEC_COMMAND", data);},// 获取节点位置getNodePosition({ commit }, data) {commit("NODE_POSITION", data);},// 切换视图changeView({ commit }, data) {commit("CHANGE_VIEW", data);},
};

Mutations-types 文件

为了让整个项目的 mutation 可以很方便的查看和管理,我们将全部的 Mutation 事件类型的名字使用常量来代替,并将它们单独存放在一个文件中,对外提供导出接口。

mutations-types.js 代码内容如下:

export const SHOW_DROP_LIST = "SHOW_DROP_LIST";
export const UPDATE_CONTENT = "UPDATE_CONTENT";
export const UPDATE_SELECTED_VALUE = "UPDATE_SELECTED_VALUE";
export const UPDATE_MENU_STATUS = "UPDATE_MENU_STATUS";
export const EXEC_COMMAND = "EXEC_COMMAND";
export const CHANGE_VIEW = "CHANGE_VIEW";
export const NODE_POSITION = "NODE_POSITION";

在 action 中提交的 mutation 的名字,和这里的名字是保持一致的。

Mutation 文件

在这个文件中,定义了很多 mutation 用于改变 store 中的数据。在 action 中提交的 mutation 都将在这里真正生效。

首先,我们需要从mutations-types 中导入 mutation 的事件名称。这里使用对象结构的方式操作:

mutations.js 代码内容如下:

// 导入事件类型
import {// 下拉框事件类型SHOW_DROP_LIST,// 更新编辑区内容事件类型UPDATE_CONTENT,// 更新选择的值事件类型UPDATE_SELECTED_VALUE,// 更新菜单状态事件类型UPDATE_MENU_STATUS,// 执行命令事件类型EXEC_COMMAND,// 获取节点位置事件类型NODE_POSITION,// 切换视图事件类型CHANGE_VIEW,
} from "./mutations-types";// 定义处理各个事件类型的回调函数
export default {[SHOW_DROP_LIST]({ menuBar }, data) {// 下拉框事件类型对回调函数for (let menu in menuBar) {if (menuBar[menu].showDropList !== undefined) {if (data && data.name === menu) {menuBar[menu].showDropList = data.display;} else {menuBar[menu].showDropList = false;}}}},[UPDATE_CONTENT](state, data) {// 更新编辑区内容事件类型state.content = data;},[UPDATE_MENU_STATUS]({ menuBar }, data) {// 更新菜单状态事件类型if ("all" in data) {for (let menu in menuBar) {menuBar[menu].status = data.all;}return;}for (let name in data) {if (menuBar[name].showStatus) {menuBar[name].status = data[name];} else {menuBar[name].status = "default";}}},[UPDATE_SELECTED_VALUE]({ menuBar }, data) {// 更新选择的值事件类型menuBar[data.name].value = data.value;},[EXEC_COMMAND](state, data) {// 执行命令事件类型state.command = data;},[CHANGE_VIEW](state, data) {// 切换视图事件类型state.sourceView = data;},[NODE_POSITION](state, data) {// 获取节点位置事件类型state.position = {top: data.top,right: data.right,bottom: data.bottom + document.body.scrollTop,left: data.left,};},
};

Index

这个文件是保存数据的地方,状态数据的改变最终都会作用到里面的数据。 store 对象的实例也由这个文件导出。

index.js 的代码内容如下:

import { createStore } from "vuex";
// 导入一些依赖模块
import mutations from "./mutations";
import action from "./action";
import Menu from "@/config/menu";
import Config from "@/config/index";let menuBar = {}; // 菜单栏对象
let menu = Menu.getMenu(); // 获取全部菜单项配置信息
let config = Config.getConfig(); // 获取全部配置项
let viewMenu = config.viewMenu; // 获取可见的菜单项viewMenu.forEach(function (name) {menuBar[name] = {};// 是否有下拉框if (menu[name].dropList) {menuBar[name].value = "";menuBar[name].showDropList = false;} else {// 是否展示状态if (menu[name].showStatus) {menuBar[name].showStatus = true;}menuBar[name].status = "default";}
});export default createStore({state: {// 编辑区域内容content: config.container.content,// 菜单栏对象,包含菜单项状态数据menuBar,// 是否源码视图sourceView: false,//执行的命令command: {name: "",value: "",},//存放位置信息position: {top: 0,right: 0,bottom: 0,left: 0,},},getters: {},mutations: mutations,actions: action,modules: {},
});

以上所有操作完成之后,我们的 vuex 就配置完成了。不过目前还不能在组件中使用,因为还没将它注入到组件中去。在组件中使用 vuex 的方式有两种,一种是在每个单独的组件中都实例化一个 store 对象,然后对 store 实例对象进行操作。另外一种方式是通过在根组件处注入 store 实例,其他所有子组件可通过 this.$store 来访问到 store 实例对象,并进行操作。推荐使用第二种方式,更加简单方便。

我们修改一下入口文件 src/main.js,注册 Vuex 实列 srore 对象:

import { createApp } from 'vue'
import App from './App.vue'
import store from './store';createApp(App).use(store).mount('#app')

ok,这样我们的项目就引入了 Vuex 了。

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

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

相关文章

electron-vite中的ipc通信

1. 概述 再electron中&#xff0c;进程间的通信通过ipcMain和ipcRenderer模块&#xff0c;这些通道是任意和双向的 1.1. 什么是上下文隔离进程 ipc通道是通过预加载脚本绑定到window对象的electron对象属性上的 2. 通信方式 2.1. ipcMain&#xff08;也就是渲染进程向主进…

C++类与对象(四):再谈构造函数(详解初始化列表)、Static成员

上次把默认的成员函数部分梳理完毕了&#xff1a;C初阶类与对象&#xff08;三&#xff09;&#xff1a;详解复制构造函数和运算符重载 今天接着讲下面的内容&#xff1a; 文章目录 1.再谈构造函数1.1构造函数体赋值1.2初始化列表1.2.1格式和概念1.2.2由来情况1情况2 1.2.3特性…

01 静态路由

静态路由是一种路由方式,其中网络管理员手动配置网络路由表,将目标网络的IP地址与下一跳的路由器IP地址相关联。这种配置是固定的,不会自动更新。当数据包到达路由器时,它会根据路由表中的静态路由规则,将数据包转发到适当的目的地。静态路由的优点是简单、可靠,因为路由…

官方版2345加速浏览器(好用的浏览器分享)

官方版2345加速浏览器&#xff08;好用的浏览器分享&#xff09; 2345加速浏览器拥有智能拦截骚扰广告&#xff0c;识别欺诈网站&#xff0c;云收藏夹等功能&#xff0c;高速上网、不假死、不卡机&#xff0c;是一款强大的多功能网页浏览器。 使用2345加速浏览器,您可以轻松应对…

前端打同一个包可以从测试晋升到生产的配置方案

前端打同一个包从测试晋升到生产环境的方案&#xff0c;是一种高效、可靠且易于维护的部署方式。在这种方案中&#xff0c;前端代码在开发完成后&#xff0c;经过测试验证无误后&#xff0c;可以直接打包部署到生产环境&#xff0c;无需进行额外的配置或修改。这样可以减少部署…

Linux系统安装NFS服务器

NFS是一种网络文件系统&#xff0c;英文全称Network File System&#xff0c;通过NFS可以让不同的主机系统之间共享文件或目录。通过NFS&#xff0c;用户可以直接在本地NFS客户端读写NFS服务端上的文件&#xff0c;是非常好的共享存储工具。本篇文章将介绍如何在CentOS7上安装N…

Netty-Netty源码分析流程图

netty服务端流程图 补充

爬虫入门学习(二)——response对象

大家好&#xff01;我是码银&#xff0c;代码的码&#xff0c;银子的银&#x1f970; 欢迎关注&#x1f970;&#xff1a; CSDN&#xff1a;码银 公众号&#xff1a;码银学编程 前言 在本篇文章&#xff0c;我们继续讨论request模块。从上一节&#xff08;爬虫学习(1)--reque…

Jmeter 性能 —— Linux下压测错误排查+解决!

排除错误日志一般方法&#xff1a; 查看脚本执行错误日志->接口返回异常查看服务器日志&#xff0c;检查是否是参数导致的问题或代码逻辑问题->出现网络相关&#xff0c;先优化压测及网络配置再压测 1、Linux下性能压测报错&#xff0c;查看错误日志 在压测机的Jmeter…

C++--右值引用

一.左右值 在C中&#xff0c;有左值和右值的概念。 左值&#xff08;lvalue&#xff09;表示一个可以获取其地址的表达式&#xff0c;或者说是一个具名的对象或函数。它可以在等号左边出现&#xff0c;也可以在等号右边出现。例如&#xff1a; int x 10; // x 是一个左值 i…

在微信公众号上怎么做报名链接_让你的活动报名与众不同

微信公众号报名链接&#xff1a;引领潮流&#xff0c;让你的活动报名与众不同 在这个信息爆炸的时代&#xff0c;微信早已成为我们生活中不可或缺的一部分。而微信公众号&#xff0c;更是成为了企业和个人传递信息、推广品牌的重要平台。如何在众多的微信公众号中脱颖而出&…

OceanBase集群扩缩容

​ OceanBase 数据库采用 Shared-Nothing 架构&#xff0c;各个节点之间完全对等&#xff0c;每个节点都有自己的 SQL 引擎、存储引擎、事务引擎&#xff0c;天然支持多租户&#xff0c;租户间资源、数据隔离&#xff0c;集群运行的最小资源单元是Unit&#xff0c;每个租户在每…