1.表格中点击编辑单元格或编辑行时会出现高度增加,有抖动现象。
原因:表格展示单行文本的高度是48px,但如果有表单元素会变成53px 解决方案:可以调整cell的height和line-height和表单元素保持一致



2.动态增加一个列后表格错位了 固定列错位了,不加fixed没问题
解决方式
js
handleColumnChange(selectColumns) {
this.dynamicColumns = selectColumns;
this.$nextTick(() => {
// doLayout 方法,用于重新计算 Table 的布局, 解决表格莫名抖动的问题
this.$refs.valuationTableRef && this.$refs.valuationTableRef.doLayout();
});
}

3.编辑表格行会出现输入框后面有...的样式,如下
原因:表单元素设置的宽度超出了单元格实际的内容区域。
解决:把表单元素的宽度设置小一点。或者把表格单元格列宽度给大点




4.hover到子元素身上,怎么修复父元素的样式

方法:
scss
.el-input-number__decrease:hover:not(.is-disabled)
~ .el-input
.el-input__inner:not(.is-disabled),
.el-input-number__increase:hover:not(.is-disabled)
~ .el-input
.el-input__inner:not(.is-disabled) {
border-color: rgb(245, 108, 108);
}
学习一些相关的css选择器,比如not,~,参照链接


5.表格如果需要固定表头,需要设置height属性,那表格高度该怎么设置?
1.设置固定高度
以固定设置为10行的高度。会出现只有2列 底下表格留白的情况。
2.设置动态高度
会出现折行的话即使只有2列也会出现滚动条的情况,和表格数据从无到有loading闪烁的情况。
那么应该怎么设置呢,建议表单单元行固定,不要折行。这样可以动态计算。并且需要注意一个小细节,就是不折行的情况,将表格高度动态设置成列表的高度,只有2列也会出现滚动条。因为1px的上边框导致的。
动态计算高度,为啥只有2行并且没有折行还会出现滚动条? 代码示例:
js
computed: {
tableHeight() {
return Math.min((this.tableData.length + 1) * 53+1, 11 * 53 + 1);
}
}
原因分析: 
分析 每行的高度是53 ,53*3 = 159
159-53(表头)= 106px(实际内容高度)。
但是el-table__body-wrapper计算出来的高度只有105px.106>105内容超出,产生滚动条。(由外层div实际的高度减去表头的高度。158-53 = 105px

为啥呢?
因为盒子实际高度只有158px ,有1px的上边框。border-box内减模式

看 如果设置成content-box就是对的。

6.方法和计算属性应该怎么选?
本来想着用计算属性优化下面代码,在el-cascader层级选择器变化时给data中的currentTzxmgzType赋值,用map定义数据,结果发现有的情况下估值方法并不可选择。所以还是只能用方法了。
js
getEditableCells (tzxmgzType) {
let editableCells
switch (tzxmgzType) {
// 已上市
case TZXMGZ_TYPE.ON_MARKET:
editableCells = ['closePrice', 'liquidityDiscount'] // 估值日收盘价 流动性折扣率
break
// 拟上市 距拟申报时间超过12个月
case TZXMGZ_TYPE.OVER_ONEYEAR:
editableCells = ['lastestFinancingPrice'] // 最新融资价格
break
// 拟上市 距拟申报时间不足12个月 有最新融资
case TZXMGZ_TYPE.HAS_FINANCING:
editableCells = ['lastestFinancingPrice'] // 最新融资价格
break
// 拟上市 距拟申报时间不足12个月 无最新融资
case TZXMGZ_TYPE.WITHOUT_FINANCING:
editableCells = ['netProfit', 'pe', 'listingDilutionRatio', 'liquidityDiscount', 'listingCirculation'] // 估值期净利润 行业分类PE中位数 上市稀释倍数 流动性折扣率 上市折扣率
break
case TZXMGZ_TYPE.NETASSETS:
editableCells = ['netAsset'] // 被投企业净资产
break
case TZXMGZ_TYPE.FINANCING_LESS_SIXMONTH:
editableCells = ['lastestFinancingPrice'] // 最新融资价格
break
default:
editableCells = []
}
return editableCells
},
// 估值日收盘价 可编辑
isClosePriceEditable (tzxmgzType) {
return this.getEditableCells(tzxmgzType).includes('closePrice')
},
结果发现有的方法是不能编辑的
7.给描述列表组件添加圆角样式
1.不能直接给table添加,不会生效。因为border-radius和border-collapse不兼容。
2.不能直接给th,td添加,这样每个单元格都有圆角,不合需求。
3.做法,修改组件样式。将table的border-collapse设置为separate,border-spacing设置为0.
css
// 修改描述列表组件样式
.el-descriptions {
// 带边框table样式重写
.is-bordered {
border-collapse: separate;
border-radius: 10px;
border-spacing: 0;
border: 1px solid #dcdde4;
overflow: hidden;
// 最后一个tbody的下边框为0
tbody:last-child {
.el-descriptions-row {
.el-descriptions-item__cell {
border-bottom: 0;
}
}
}
// 表格每个单元格的样式
.el-descriptions-item__cell {
border: none;
border-right: 1px solid #dcdde4;
border-bottom: 1px solid #dcdde4;
&:last-child {
border-right: 0;
}
&.el-descriptions-item__label {
background: #f2f3f8;
font-family: PingFangSC-Medium;
color: #868a9e;
font-weight: 500;
&.describeLabel {
width: 150px;
}
}
&.el-descriptions-item__content {
font-family: PingFangSC-Regular;
color: #0f1f45;
font-weight: 400;
}
}
}
}
8.新增编辑表单组件中打开编辑弹窗后关闭,再打开新增弹窗,编辑弹窗的id没有置空,导致新增接口报错:存在重复id.
问题根本原因:新增表单中包含上次编辑表单中的数据。
问题解决方式: 1.关闭弹窗时需要调用表单的resetFields方法把表单数据清空,如下
js
closeDialog() {
this.dialogVisible = false;
// 关闭弹窗时把表单数据清空 避免点击新增弹窗时保留之前的编辑数据
this.$refs.addEditFormRef && this.$refs.addEditFormRef.resetFields()
},

2.在点击新增时把数据置空,我是这样写的
js
handleAdd() {
this.handleEdit({})
},
handleEdit(row) {
this.$refs.formRef.resetFields();
this.$nextTick(()=>{
this.localFormData = Object.assign({}, row);
})
},
3.上面2步做了但是发现还是有问题,我们看下问题代码吧.其实出错的地方在这里
js
model: {
prop: "formData",
event: "input"
},
computed: {
localFormData:{
get(){
return this.formData;
},
set(nextValue){
//bad
// Object.assign(this.formData,nextValue)
//good
this.$emit('input',nextValue)
}
}
},
Object.assign,用于对象的合并。点击编辑时this.localFormData其实已经复制了row的数据,此时row里面包含id;此时再点击新增,其实只是复制了部分值,formData里面包含的。对应没有包含的id还是存在的。那应该怎么修改呢?只需要改set里面的代码就好了。
9.表单的inline和el-col不建议一起使用。设置为inline后 el-inform-item变为inline-block,width由内容撑开;但是默认为block会继承父元素的宽度。
现象:中间间剧很大


去掉form表单的inline属性后就排列的紧凑一些,当然如果是select时记得设置width:100%,继承父元素的宽度

10.运算符的逻辑短路 : && 如果第一个值为false,则不会看第二个值; || 如果第一个值为true,则不会检查第二个值
11.el-dialog与el-tab一起使用,导致关闭弹窗时页面进入死循环
vue版本:2.5.16,element-ui版本:2.15.9
bug存在条件: 1.在el-dialog 上 配置了destroy-on-close属性
2.el-tab-pane标签中有内容。
bug解决方式:
1.去掉destroy-on-close,实际这个属性不知道用来干嘛的,测试过程中加了该属性元素并没有销毁

2.el-tab-pane标签中的内容写在组件外面,可以使用动态组件的方式,
ruby
<component :is=""></component>
3.我自己临时解决的,自己手写了个简单的tab,没有使用element-ui的tab组件。
网上提供的方式:

bug原因分析,这篇文章写的比较详细。
实际和组件的渲染机制有关,在子组件updated时更改状态,会导致一直陷入循环!关于这一点,vue官网有介绍:

12.el-cascader组件使用过程中的坑
在项目中有些数据有一定的架构体系,比如部门等,此时需要用到cascader级联选择器或者tree树形控件。在实际使用cascader组件过程中遇到一些坑:
- 1.在单选模式下选择任意一级选项并且选中后仅显示最后一级,当时和后端定义的数据格式是
String类型。此时传入后端参数需要额外处理,如果是字符串则直接传(初始化进入不做任何change),如果是数组类型则截取数组的最后一项(组件change后双向绑定的数据是数组格式)。然后回显和新建编辑都能实现了,但是没有注意到radio并没有选中。后面经过一番测试验证,发现必须得是数组格式才能正常展示radio的选中态,并且数组中必须包含完整的父级关系。后面又和后端沟通增加一个字段进行数据的绑定,果然问题得以解决!

- 2.新增选择部门时,前端校验如果为空,则进行必填项校验。在第一次新增选择了部门后调用接口新增成功,此时不做任何页面的刷新和切换,再次打开新增弹窗,数据清空了,但是校验不生效,可以直接点击新增按钮调用接口。我通常会在关闭弹窗时清空表单的校验,像下面这样
js
closeDialog() {
this.dialogVisible = false;
this.$refs.formRef && this.$refs.formRef.resetFields();
}
咦,我明明将字段重置为初始值并且移除了校验结果呀,怎么不生效呢,log下对应的字段看下

实际我在项目中定义的是一个字符串,但是这里确变成了数组格式,也不知道咋回事???难道重置初始值会默认变成组件内部的初始值!!!所以我还是不改变组件的数据格式,将deptId定义为数组格式后完美解决了问题!
这一次的经验加上上次radio值定义,得出还是严格按照组件的要求定义数据格式才能完美规避一些不太常见的坑!!!
13.怎么解决浮点数计算精度丢失的问题
- 1.可以将对应的浮点数转成整数进行计算,计算完后再转成浮点数
- 2.使用toFixed方法,但是注意此方法会把数字转成字符串哦
- 3.借助第三方库,比如Big.js,decimal.js
14.el-table表格实现多选和对选中的行进行校验

2.可以通过fields属性获取所有需要校验的字段,eg
js
const allFieldsProp = this.$refs.idFormRef.fields.map(item => item.prop);
3.注意validateField是对校验字段进行逐个校验,如果需要所有的校验成功,才进行对应提示,可以借助Promise.all()方法,eg
js
//全部校验成功返回true,只要有一个校验不成功就返回false
async handleValidate() {
this.getVertifyFields(this.multipleSelection);
const validateOneField = field => {
return new Promise(resolve => {
this.$refs.idFormRef.validateField(field, errorMsg => {
resolve(errorMsg);
});
});
};
const validateAllFields = this.selectedVerifyFileds.map(item => {
return validateOneField(item);
});
const errorMsgList = await Promise.all(validateAllFields);
const isValid = errorMsgList.every(item => !item);
return isValid;
},
参考文章:blog.csdn.net/weixin_4861...
15.el-table设置多选时对选中的数据进行保存后,刷新了列表数据,怎么保留勾选框的选中状态
1.前提是后端没有进行更新时间排序,如果进行了更新时间排序,操作保存的数据会刷新到第一页,无法在当前页中找到该数据设置选中态
2.使用toggleRowSelection api设置选中和不选中状态



注意:官网示例是直接改变表格数据源
3.那自己实现一下吧,在保存成功,loadData()后设置选中态,却发现怎么也不生效!因为在项目的实际场景中,watch数据变化后又对数据进行了处理,改变了数据的指针,所以在watch做操作发现就可以了!
js
watch: {
"tableProps.tableData": {
handler(nextValue) {
const processedTreeData = this.handleTableData(nextValue);
this.tableFormData.tableData = processedTreeData;
if (this.multipleSelection) {
this.multipleSelection.forEach(row => {
this.$nextTick(() => {
this.tableFormData.tableData.find(item => {
if (row.id === item.id) {
this.$refs.multipleTableRef.toggleRowSelection(item, true);
}
});
});
});
}
},
deep: true
}
},
总结: 1.为啥数据刷新后选中状态就消失了呢?数据更新后Dom会注销新建,导致我们勾选操作失效 2.必须操作表格源数据,如果数据指针发生变化,设置选中态也不会生效 3.如果获取不到dom,可以使用$nextTick,因为Vue的视图更新是异步的,即数据变了dom并不会立马更新

参考:blog.csdn.net/Centenario_...
16.有这样一个简单的需求,表格第一行展示2个单元格,第一个单元格宽度要大;第二行及以上展示3个单元格,那么第一个单元格宽度肯定要小呀,常规用v-if怎么都实现不了呀。因为如果只在第二行展示一个图片标签,第一行虽然不展示,但是根据表格的特性还是占有宽度,那么怎么解决呢?看了下el-table组件的api,合并单元格加动态样式就搞定了


实际实现如下: 1.第一行第一列合并单元格
ini
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 0) {
if (columnIndex === 0) {
return [1, 2];
} else if (columnIndex === 1) {
return [0, 0];
}
}
},
2.增加上述代码后发现第一行确实只有2个单元格了,但是实际内容宽度并没有减少,
, 于是想着怎么让这个单元格的宽度继承父的宽度呢,只要加一个样式覆盖一下即可

又查找了下api,发现

增加类
js
getCellClassName({row, column, rowIndex, columnIndex}){
if(rowIndex===0 && columnIndex===0){
return 'digest-cell'
}
},
如上,就解决了,要是一开始就是我做的,可能不选择表格了,自己也个列表应该是很容易的了!
总结:
-
1.table 上增加span-method可以合并单元格
-
2.想要给某个单元格添加样式可以使用cell-class-name 属性
16.开发时页面功能明明都是正常的,测试时确发现页面一直loading,请求也没有发出去
hi,这是一个2024春节前开发时遇到的一个有趣的问题,直到过完年后才被解决,解决方式也很简单,但是中间的过程也是值得record一下的!需求很简单:页面上有2个表格,分别请求对应的列表接口,并且需要30分钟刷新一次列表。想实现的是2个列表都请求成功,刷新时给用户成功的提示,如果其中一个失败则只提示对应的失败信息。当时立马就想到了Promise.all处理并发请求(2个接口没有依赖关系),但是还有一个方法Promise.allSettled没有用过,所以想用一下。好了,本地开发结束,一切符合预期,但是测试时因为是从别的堡垒机访问我的ip地址,结果一直loading,严重阻塞了。。。
当时第一反应可能是网络限制,但是也不对,实际网络请求都没发出;接着就想到了可能是高级语法Promise.allSettled的浏览器兼容性问题,于是改成了Promise.all,还是loading;没办法年后去同事电脑上看,结果发现控制台报错,是replaceAll那一行,查看Can I Use查看是否支持,原来是这个不支持。。。哎,年前其实也去看过,当时断点没太看懂没太注意到报错。。。于是换成replace 分分钟解决!同事chrome浏览器版本是82.几,我的是110.几的,replaceAll支持chrome85.几的。。。,so,项目中还是慎用replaceAll,至于babel为啥没转成功就不知道了?


17.需求:el-table表格展示,根据正负数对单元格内容进行颜色区分,并将数字进行千分位展示。
bug:使用formatter函数
ini
<el-table-column
prop="discountPremium"
label="溢折价"
min-width="160px"
:formatter="formatDiscountPremium"
>
</el-table-column>
javascript
formatDiscountPremium(row, column, cellValue, index) {
console.log("cellValue---", cellValue, cellValue > 0);
// TODO:转成千分位
if (Math.sign(cellValue) > 0) {
return <span style="color:#db3d54">{{ cellValue }}</span>;
} else if (Math.sign(cellValue) < 0) {
return <span style="color:#3d8e2f">{{ cellValue }}</span>;
} else {
return <span>-</span>;
}
}
上面代码示例实际会显示为undefined,有颜色。因为{{}}是在tempalte模板才能解析的,js语法无法解析。正确
ini
<el-table-column
prop="discountPremium"
label="溢折价"
min-width="160px"
>
<template slot-scope="{row}">
<div class="cell" v-html="formatDiscountPremium(row.discountPremium)"></div>
</template>
</el-table-column>
javascript
formatDiscountPremium(cellValue) {
const discountPremium = this.numberFormat(cellValue)
if (Math.sign(cellValue) > 0) {
return `<span style="color:#db3d54">${discountPremium}</span>`;
} else if (Math.sign(cellValue) < 0) {
return `<span style="color:#3d8e2f">${discountPremium}</span>`;
} else {
return `<span>-</span>`;
}
},