当前位置: 首页 > news >正文

Vue - 基于Element UI封装一个表格动态列组件

1 组件需求背景

在后台管理系统中,表格的使用频率非常高,统一封装表格动态列组件并全局注册使用,可大大提升代码的复用性可维护性

2 全局注册

  • src/plugins/index.js:
import columns from './columns/index'export default {install(Vue) {// 动态列Vue.prototype.$columns = columns}
}
  • src/main.js:
import plugins from './plugins' // plugins
// 表格动态列组件
import DynamicColumn from '@/components/DynamicColumn'
Vue.component('DynamicColumn', DynamicColumn)
Vue.use(plugins)
  • 页面(Page.vue)中使用
 <DynamicColumnv-for="(ite, index) in columns":key="index":item="ite":data-list="infoList"/>infoList: [],
columns: this.$columns.getColumns('investmentDecision_list'),

Vue注册组件相关内容可见我的另外一篇博客:Vue - 组件注册及其原理

3 具体组件相关代码

  • src/plugins/columns/index.js:
const columns = {getColumns: function(columnType) {const list = columnList[columnType].listconst newColumn = []list.forEach((v, i) => {newColumn.push({...v,visible: v.visible === undefined ? true : v.visible, // 是否显示字段prop: v.prop, // 字段keylabel: v.label, // 字段名称align: v.align, // 对齐方式sortable: v.sortable, // 是否排序inputType: v.inputType, // 输入方式fixed: v.fixed, // 是否固定列tip: v.tip, // 是否列名解析width: v.width, // 列宽unit: v.unit, // 后缀,如"%"等keepDecimals: v.keepDecimals, // 保留小数位formatThousand: v.formatThousand, // 是否格式化千分位division: v.division, // 是否需要除数,如格式化万则需要除10000class: v.class, // 样式style: v.style, // 样式disabled: v.disabled, // 禁用controls: v.controls,tagTypeStyle: v.tagTypeStyle, // tag标签风格,函数类型,返回一个字符串,参考值为:default | primary | success | info | warning | dangerrender: v.render, // 渲染函数,返回一个处理后的值展示到页面中min: v.min, // 最小值max: v.max, // 最大值routerLink: v.routerLink,chartType: v.chartType, // Echart 图表类型,参考值为:1代表柱形折线图,2代表饼图chartData: v.chartData, // Echart 图表数据chartKey: v.chartKey, // Echart 图表Id的后缀columnTagText: v.columnTagText // 列标签标识})})return newColumn}
}export default columns
  • src/components/DynamicColumn.vue:
<!--动态列-->
<template><!-- :key="`${item.prop}+${item.label}`" --><!-- :show-overflow-tooltip="!item.chartType" --><el-table-columnv-if="item.visible":key="item.prop==='secCode'?Math.random():`${item.prop}+${item.label}`":prop="item.prop":label="item.label":fixed="item.fixed":min-width="getCellWidth(item,dataList)":align="item.align||'left'":show-overflow-tooltip="true":sortable="item.sortable"><template slot="header"><el-tooltipv-if="item.tip"class="item"effect="dark":content="item.tip"placement="top-start"><span><span v-if="item.valid" style="color: #ec051b; font-size: 1.5em">*</span><span>{{ item.label }}</span><i class="el-icon-question" /></span></el-tooltip><span v-else><span v-if="item.valid" style="color: #ec051b; font-size: 1.5em">*</span><span>{{ item.label }}</span></span></template><template slot-scope="scope"><el-inputv-if="item.inputType === 'input'"v-model="scope.row[item.prop]"size="mini":placeholder="$t('pleaseEnter')":disabled="item.disabled||(scope.row.disabled&&scope.row.disabled.includes(item.prop))"@change="onChange(scope.row,item)"@blur="onBlur(scope.row,item)"/><el-input-numberv-else-if="item.inputType === 'number'"v-model="scope.row[item.prop]"size="mini":placeholder="$t('pleaseEnter')":precision="item.keepDecimals":controls="item.controls":min="item.min":max="item.max":disabled="item.disabled||(scope.row.disabled&&scope.row.disabled.includes(item.prop))"@change="onChange(scope.row,item)"@blur="onBlur(scope.row,item)"/><el-selectv-else-if="item.inputType === 'select'"v-model="scope.row[item.prop]":placeholder="$t('pleaseSelect')"size="mini":disabled="item.disabled||(scope.row.disabled&&scope.row.disabled.includes(item.prop))"@click.native="lastValue = scope.row[item.prop]"@change="onChange(scope.row,item)"><el-optionv-for="ite in scope.row[item.prop + 'list'] || []":key="ite.value":label="ite.label":value="ite.value":disabled="ite.disabled"/></el-select><el-date-pickerv-else-if="item.inputType === 'date'"v-model="scope.row[item.prop]":format="item.format||'yyyy-MM-dd'":value-format="item.format||'yyyy-MM-dd'":type="item.dateType||'date'":placeholder="$t('pleaseSelect')":disabled="item.disabled||(scope.row.disabled&&scope.row.disabled.includes(item.prop))"size="mini"@change="onChange(scope.row,item)"/><el-switchv-else-if="item.inputType === 'switch'"v-model="scope.row[item.prop]":active-text="item.activeText":inactive-text="item.inactiveText":active-value="item.activeValue":inactive-value="item.inactiveValue"@change="onChange(scope.row,item)"/><el-radio-groupv-else-if="item.inputType === 'radio'"v-model="scope.row[item.prop]":disabled="item.disabled||(scope.row.disabled&&scope.row.disabled.includes(item.prop))"@change="onChange(scope.row,item)"><el-radiov-for="ite in scope.row[item.prop + 'List'] || []":key="ite.value":disabled="ite.disabled":label="ite.value">{{ ite.label }}</el-radio></el-radio-group><el-checkboxv-else-if="item.inputType === 'checkbox' && scope.row[item.prop]!==undefined"v-model="scope.row[item.prop]":disabled="item.disabled||(scope.row.disabled&&scope.row.disabled.includes(item.prop))"@change="onChange(scope.row,item)">{{ scope.row[item.prop+"Label"] }}</el-checkbox><el-tagv-else-if="item.tagTypeStyle":disable-transitions="true":type="item.tagTypeStyle(scope.row,scope.row[item.prop])||'primary'">{{ formatter(scope.row, item) }}</el-tag><router-linkv-else-if="!item.columnTagText && item.routerLink && item.routerLink(scope.row)"class="dy-router-link":to="item.routerLink(scope.row)"><span>{{ formatter(scope.row, item) }}</span></router-link><BarLineChartv-else-if="item.chartType==1 && scope.row[item.prop]":dom-id="`${scope.row[item.chartKey]}${item.prop}`":data="scope.row[item.prop]"height="50px"background-color="transparent"/><!-- <GridsBarLineChartv-else-if="item.chartType==2 && scope.row.chartData":dom-id="`${scope.row[item.chartKey]}${item.prop}`":data="scope.row.chartData"height="50px"/>--><divv-else-if="item.columnTagText":class="item.class":style="item.style"@click="handleClick(scope.row,item)"><div v-if="item.routerLink && item.routerLink(scope.row)"><router-link class="dy-router-link" :to="item.routerLink(scope.row)"><span>{{ formatter(scope.row, item) }}</span></router-link><div style="margin-top: -8px;"><el-tagv-if="item.columnTagText(scope.row)"type="danger"size="mini">{{ item.columnTagText(scope.row) }}</el-tag></div></div><div v-else>{{ formatter(scope.row, item) }}</div></div><spanv-else:class="item.class":style="item.style"@click="handleClick(scope.row,item)">{{ formatter(scope.row, item) }}</span></template></el-table-column>
</template><script>
import { moneyFormat, keepDecimals, isNumber } from '@/utils/utils'
import Sortable from 'sortablejs'
// 组件
import BarLineChart from '@/components/Echarts/BarLineChart'export default {components: {BarLineChart},props: {// 非必传,只有存在多个表格时,该参数作为表格的唯一标识,主要用于拖拽tableSign: {type: String,default: null},// 所有的列字段,用于拖拽schemas: {type: Array,default: () => {return []}},// 不在schemas内,并且在动态列之前的列数empty: {type: Number,default: 0},// 列字段item: {type: Object,default: () => {return {}}},// 自定义格式化方法format: {type: Function,default: null},// 自定义格式化方法对应的字段formatColumns: {type: Function,default: () => {return []}},// 表格数据dataList: {type: Array,default: () => []}},data() {return {lastValue: undefined // 上次的值}},mounted() {// 表格拖拽方法if (this.schemas.length > 0) {this.columnDrop()}},methods: {// 计算列宽(因为element自适应的宽度还是存在部分字段名称换行情况,所以需要重新计算)getCellWidth(item, dataList) {const { label, width: defaultWidth } = itemif (defaultWidth) {return defaultWidth}if (!label) {return 0}let renderTextMax = ''if (dataList.length > 0) {dataList.forEach((row) => {// 取内容文本的最大值const renderText = this.formatter(row, item) ?? ''this.calculateWidth(renderText) >this.calculateWidth(renderTextMax) && (renderTextMax = renderText)})}// 取表头和内容文本的较大值this.calculateWidth(label) > this.calculateWidth(renderTextMax) &&(renderTextMax = label)let width = 0const html = document.createElement('span')html.innerText = renderTextMaxhtml.className = 'getTextWidth'document.querySelector('body').appendChild(html)width = document.querySelector('.getTextWidth').offsetWidthdocument.querySelector('.getTextWidth').remove()if (width > 260) {return 280}return width + 20},// 计算字符宽度calculateWidth(renderText) {let flexWidth = 0for (let i = 0; i < String(renderText).length; i++) {const char = renderText[i]if ((char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z')) {// 如果是英文字符,为字符分配8个单位宽度flexWidth += 8} else if (char >= '\u4e00' && char <= '\u9fa5') {// 如果是中文字符,为字符分配16个单位宽度flexWidth += 16} else {// 其他种类字符,为字符分配8个单位宽度flexWidth += 8}}return flexWidth},// change事件,向父组件传递字段和值onChange(row, item) {row.oldValue = this.lastValue // 传选择之前的值this.setItemAndValue(this.$parent, row, item, 'columnChange')},// 点击事件,icon点击向父组件传递对应的字段信息handleClick(row, item) {this.setItemAndValue(this.$parent, row, item, 'columnClick')},// 失去焦点事件,icon点击向父组件传递对应的字段信息onBlur(row, item) {this.setItemAndValue(this.$parent, row, item, 'onBlur')},/*** @function setItemAndValue 向父组件传递相应的字段和值* @param {Object} parent 父组件原型* @param {Object} item 字段信息* @param {*} value 值* @param {String} functionType 函数类型*/setItemAndValue(parent, row, item, functionType) {if (parent && parent[functionType]) {parent[functionType](row, item)} else {if (parent.$parent) {this.setItemAndValue(parent.$parent, row, item, functionType)}}},// 格式化formatter(row, item) {// render优先级最高if (item.render) {return item.render(row, row[item.prop])}if (row[item.prop] === null ||row[item.prop] === undefined ||row[item.prop] === '') {// value为0或者false还是照样原来显示return '--'}let value = row[item.prop]if (this.format) {if (this.formatColumns.length > 0 &&this.formatColumns.includes(item.prop)) {// 指定自定义格式化的字段return this.format(row, item, row[item.prop])} else {// 未指定的往下走value = this.format(row, item, row[item.prop])}}if (isNumber(value)) {if (item.keepDecimals || item.keepDecimals === 0) {// 保留小数位value = keepDecimals(value, item.keepDecimals, item.division)}if (item.formatThousand) {value = moneyFormat(value, item.division) // 千分位}if (item.unit) {// 是否带单位,如万value = value + item.unit}}return value},/*** 列拖拽*/columnDrop() {// 页面多个表格 取到对应表格dom元素let wrapperClass = '.el-table__header-wrapper'if (this.tableSign) {const elClass = this.$parent.$el.getAttribute('class')if (!elClass.includes(this.tableSign)) {this.$parent.$el.setAttribute('class', `${elClass} ${this.tableSign}`)}wrapperClass = `.${this.tableSign} ${wrapperClass}`}const wrapperTr = document.querySelector(`${wrapperClass} tr`)this.sortable = Sortable.create(wrapperTr, {animation: 100, // 过渡动画delay: 0, // 延迟多久可以拖动onEnd: (evt) => {if (evt.oldIndex === evt.newIndex) returnconst overviewColumns = [...this.schemas]const visbleColumns = overviewColumns.filter((v) => v.visible) // 显示的列const empty = this.empty // 不在schemas内,并且在动态列之前的列数// 注意:动态列表包含visible为false数据,需要进行特殊筛选处理const oldItem = visbleColumns[evt.oldIndex - empty]const newItem = visbleColumns[evt.newIndex - empty]const realOldIndex = overviewColumns.findIndex((item) => item.prop === oldItem.prop)const realNewIndex = overviewColumns.findIndex((item) => item.prop === newItem.prop)overviewColumns.splice(realOldIndex, 1) // 删除原来位置的数据overviewColumns.splice(realNewIndex, 0, oldItem) // 在新的位置插入该数据this.$emit('changeColumn', overviewColumns)}})}}
}
</script>
<style lang="scss" scoped>
.el-table__row .el-form-item {margin-bottom: 0px !important;
}.el-input,
.el-input.is-disabled,
.el-range-editor.el-input__inner,
.el-date-editor.el-input {width: 100%;
}::v-deep.el-select > .el-input {width: 100%;
}::v-deep.el-input-number .el-input {width: 100%;
}
.el-input-number {width: 100%;
}.dy-router-link {color: #1890ff;display: inline-block;max-width: 100%;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;position: relative;&:hover:after {content: '';position: absolute;top: 0;right: 0;bottom: 0;left: 0;border-bottom: 1px solid #1890ff;}
}::v-deep .el-table__row {border: 1px solid #1890ff;.el-table .cell.el-tooltip {display: flex;align-items: center;}
}
</style>

相关文章:

Vue - 基于Element UI封装一个表格动态列组件

1 组件需求背景 在后台管理系统中&#xff0c;表格的使用频率非常高&#xff0c;统一封装表格动态列组件并全局注册使用&#xff0c;可大大提升代码的复用性和可维护性。 2 全局注册 src/plugins/index.js&#xff1a; import columns from ./columns/indexexport default …...

计算机网络:DNS域名解析系统

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…...

java面试:==和equals有什么区别?

在 Java 中&#xff0c;"" 和 "equals" 有着不同的作用&#xff1a; "" 运算符&#xff1a; 在基本数据类型&#xff08;如 int、char 等&#xff09;中&#xff0c;"" 用于比较它们的值是否相等。 在引用类型中&#xff0c;"&q…...

数字人SaaS系统无限生成AI数字人!

市面上数字人软件层出不穷&#xff0c;选择一款适合的数字人软件是成功的第一步&#xff0c;只需要一款软件就解决数字人直播和数字人短视频的制作&#xff0c;青否数字人SaaS系统&#xff08;数字人源码&#xff1a;zhibo175&#xff09;你值得拥有&#xff01; 青否数字人Saa…...

【MySQL】——数据类型及字符集

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…...

Redis cluster集群设置密码

Redis cluster集群设置密码 1 备份数据 # 链接redis集群,执行rdb快照 bgsave # 备份dump.rdb文件 cp /data/redis/cluster/dump.rdb /data/redis/cluster/backup/dump.rdb.202312202 设置密码 必须保证每个节点的密码保持一致&#xff0c;不然 Redirected 的时候会失败 2.1…...

Docker 核心技术

Docker 定义&#xff1a;于 Linux 内核的 Cgroup&#xff0c;Namespace&#xff0c;以及 Union FS 等技术&#xff0c;对进程进行封装隔离&#xff0c;属于操作系统层面的虚拟化技术&#xff0c;由于隔离的进程独立于宿主和其它的隔离的进程&#xff0c;因此也称其为容器Docke…...

15 使用v-model绑定单选框

概述 使用v-model绑定单选框也比较常见&#xff0c;比如性别&#xff0c;要么是男&#xff0c;要么是女。比如单选题&#xff0c;给出多个选择&#xff0c;但是只能选择其中的一个。 在本节课中&#xff0c;我们演示一下这两种常见的用法。 基本用法 我们创建src/component…...

go语言指针变量定义及说明

go语言指针主要需要记住两个特殊符号&#xff0c; 一个是 & 用来获取变量对应的内存地址 另一个是 * 用来获取指针对应的变量值 下面是个最简单的go语言指针说明 package mainimport "fmt"//指针为内存地址func main() {var a string "指针对应的变量&…...

基于“Galera+MariaDB”搭建多主数据库集群的实例

1、什么是多主数据库集群 多主数据库集群是一种数据库集群架构&#xff0c;每个节点都可以接收写入操作和读取操作&#xff0c;并且通过心跳机制同步数据&#xff0c;保证数据一致性和高可用性。因多主数据库集群每个节点都可以承担读写操作&#xff0c;因此它可以充分利用各个…...

arcgis javascript api4.x加载天地图cgs2000坐标系

需求&#xff1a;arcgis javascript api4.x加载天地图cgs2000坐标系 效果&#xff1a; 示例代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"wid…...

算法学习——回溯算法

回溯算法 理论基础回溯法的效率回溯法解决的问题回溯法模板 组合思路回溯法三部曲 代码 组合&#xff08;优化&#xff09;组合总和III思路代码 电话号码的字母组合思路回溯法来解决n个for循环的问题回溯三部曲代码 组合总和思路代码 组合总和II思路代码 理论基础 什么是回溯法…...

C语言—小小圣诞树

这个代码会询问用户输入圣诞树的高度&#xff0c;然后根据输入的高度在控制台上显示相应高度的圣诞树。 #include <stdio.h>int main() {int height, spaces, stars;printf("请输入圣诞树的高度: ");scanf("%d", &height);spaces height - 1;st…...

Android消息公告上下滚动切换轮播实现

自定义控件 通过继承TextSwitcher实现 直接上代码 public class NoticesSwitcher extends TextSwitcher implements ViewSwitcher.ViewFactory {private Context mContext;private List<Notice> mData;private final long DEFAULT_TIME_SWITCH_INTERVAL 1000;//1spri…...

tensorflow入门 自定义模型

前面说了自定义的层&#xff0c;接下来自定义模型&#xff0c;我们以下图为例子 这个模型没啥意义&#xff0c;单纯是为了写代码实现这个模型 首先呢&#xff0c;我们看有几个部分&#xff0c;dense不需要我们实现了&#xff0c;我们就实现Res&#xff0c;为了实现那个*3,我们…...

虚拟机启动 I/O error in “xfs_read_agi+0x95“

1.在选择系统界面按e 进入维护模式 2.找到ro把ro改成 rw init/sysroot/bin/sh 然后按Ctrlx 3.找到坏掉的分区&#xff0c;以nvme0n1p3为例进行修复 xfs_repair -d /dev/nvme0n1p3 4.init 6 重新启动 以下情况 先umount 再修复 则修复成功...

【MYSQL】-库的操作

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …...

网络协议小记

一、TCP/IP协议 作为一个小萌新&#xff0c;当然我无法将tcp/ip协议的大部分江山和盘托出&#xff0c;但是其中很多面试可能问到的知识&#xff0c;我觉得有必要总结一下&#xff01; 首先&#xff0c;在学习tcp/ip协议之前&#xff0c;我们必须搞明白什么是tcp/ip协议。 1、…...

STM32-I2C通讯-AHT20温湿度检测

非常感谢&#xff0c;提供的视频学习 https://www.bilibili.com/video/BV1QN411D7ak/?spm_id_from333.788&vd_source8ca4826038edd44bb618801808a5e076 该文章注意&#xff1a;串口显示中文会乱码&#xff0c;必须选用支持ASCII的串口助手&#xff0c;才能正常显示中文。…...

【机器学习】043_准确率、精确率、召回率

一、定义 在处理偏斜数据集时&#xff0c;通常使用不同的误差度量&#xff0c;而不仅仅是使用分类误差来衡量算法性能。 1. 混淆矩阵的概念 二分类问题的混淆矩阵为2X2矩阵&#xff0c;由四部分组成&#xff1a; 假阴性&#xff08;FN&#xff09;&#xff1a;模型预测为负…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...