element小坑合集
单选和多选的选项过长不会自动换行
- 在单选和多选框外层添加类名solo,然后如下样式
::v-deep .solo .el-checkbox__label {
display: inline-grid !important;
white-space: pre-line !important;
word-wrap: break-word !important;
overflow: hidden !important;
line-height: 20px !important;
}
::v-deep .solo .el-radio__label {
display: inline-grid !important;
white-space: pre-line !important;
word-wrap: break-word !important;
overflow: hidden !important;
line-height: 20px !important;
}
表单有下拉组件,使用v-if动态显示的时候,下拉框的必填校验失效或者切换的时候会渲染错乱
- 为每一个item添加key
上传文件上传前校验函数 文件格式不正确 return false 无法拦截调取上传接口
- 修改为
return Promise.reject(false);
form表单重置失效
- 弹窗中有表单,关闭弹窗重置,但是一进来先点修改再点新增失效
- 采用下面新的方法,但是验证条件红字还在,所以两种一起使用
close(formName) {
// this.$refs[formName].resetFields(); //element的
this.resetForm(formName); //若依封装的和上面element是一样的
Object.assign(this.$data.form, this.$options.data().form)
},
form 表单中只有一个输入框,在输入框中按下回车就是提交该表单,且会刷新页面。
- 在form标签上添加
@submit.native.prevent
阻止这一默认行为
时间范围选择器在编辑页面赋值完之后,再次更改时间页面不会渲染(偶现)
- 监听change事件强制更新视图
<el-form-item label="起止日期" prop="time">
<el-date-picker v-model="form.time" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" style="width: 100%;" @input="dateRangeChange">
</el-date-picker>
</el-form-item>
dateRangeChange() {
this.$nextTick(() => {
this.$forceUpdate();
});
},
当el-form搜索框只有一个时,@keyup.enter.native事件,按enter会刷新页面
解决方案
- 给el-form标签添加@submit.native.prevent,阻止form表单的提交事件
<el-form @submit.native.prevent>
- 在el-form中放多一个el-input标签,加隐藏样式
<el-input style="display: none" />
一个 row 标签中多个 col 标签,当col 占比多于一行时,下拉框选择后导致其他表单移位
解决方案
- 每一行一个row标签
- flex布局换行,适用于部分表单有显示隐藏的情况
<el-row style=" display: flex;flex-wrap: wrap;">
</el-row>
修改弹窗,form表单输入框修改值时,数据改变但页面不更新
- 点击修改按钮,显示弹窗,给小区名字赋初始值需要使用$set() 的方式
// 修改小区或楼栋
edit(data, node) {
this.editAreaShow = true;
this.$set(this.editForm, "areaName", this.data.houseName);
// this.editForm.areaName = this.addData.houseName;
}
},
表格某行点击修改时,将 row赋值给变量,修改变量时,row也会被改变,导致表格源数据改变
- 方法一:this.data = Oblect.assign({},row) 处理一下
- 方法二:调取接口获取本行数据,不使用 row
搜索项form表单点击下拉没反应,input输不进去
- form表单数据 form:{ data1:‘’ } 需要初始化
form表单 v-model绑定的数据必须在 form 对象里,否则 校验 rules 不起作用
el-cascader组件 @change回调参数 (arr)
- arr是级联选择器每一级选中的id组成的数组
- 当初始化,重新给form赋值时,会触发change事件
- 此时arr 为 undefined,所以当使用 arr[0]时就会报错
- 所以注意在回调里先判断arr是true在写逻辑
table——操作栏右固定,显示错位
- 方法 1:操作栏宽度需要给够,不换行
- 方法 2: 全局覆盖样式
.el-table__fixed-right {
.el-table__fixed-body-wrapper {
top: 44px !important;
}
}
- 方法3:在获取数据之后触发 Table 的重新布局
this.$nextTick(() => {
this.$refs.tableComponent.doLayout()
})
公用弹窗表单组件,会出现数据错乱
解决方法:watch 弹窗组件的显示隐藏变量,当变量改变时,reset表单数据
watch: {
dialogVisible(newV, oldV) {
if (newV != oldV) {
if (!newV) {
this.resetForm("ruleForm");
}
}
},
},
element-ui 抽屉打开后自动显示最下方内容
遇到问题:
抽屉内容太长的情况下,一打开抽屉后总是展示内容最下方。
解决办法:
通过ref定位到抽屉里的dom元素,通过抽屉的open方法使得内容从顶部开始展示
<template>
<div>
<!-- 添加或修改题目信息对话框 -->
<el-drawer ref="drawer" @open="scrollToTop">
<div class="demo-drawer__content">
<!-- 超出浏览器高度内容 -->
</div>
</el-drawer>
</div>
</template>
<script>
export default {
data() {
return {};
},
methods: {
// 抽屉一打开从内容顶部开始显示
scrollToTop() {
this.$nextTick(() => {
const drawerElement = this.$refs.drawer.$el;
drawerElement.querySelector('.demo-drawer__content').scrollIntoView({ block: 'start', inline: 'nearest' });
});
},
},
};
</script>
关于scrollIntoView()方法详解与实际运用 可详见scrollIntoView()方法详解与实际运用
动态新增选项后默认选中下移
遇到问题:
假设目前选中A选项,新增后默认选中会下移
解决办法:
组件默认选中项会受动态更新的影响进行变更,所以在动态的el-radio-group中增加key值,无论是增加或是删除,都对其进行强制刷新。
<template>
<div>
<!-- 单选 -->
<el-radio-group v-model="radio" :key="radioKey">
<el-radio class="radioItem" :label="index" v-for="(item, index) in form.questionAnwserList" :key="index">
<el-input v-model="item.optionContent" size="mini"></el-input>
<!-- 减号 -->
<el-button size="mini" v-if="form.questionAnwserList.length > 1" @click="delAnswer(index)">
<i class="el-icon-close"></i>
</el-button>
<!-- 加号 -->
<el-button size="mini" @click="addAnswer()"><i class="el-icon-plus"></i></el-button>
</el-radio>
</el-radio-group>
</div>
</template>
<script>
export default {
data() {
return {
// 表单
form: {
// 题目答案列表
questionAnwserList: [
{
optionLabel: "",
optionContent: "",
correctAnswerFlag: 0,
sort: 0,
},
],
},
// 单选正确答案值
radio: 0,
// 单选key
radioKey: 0,
};
},
methods: {
// 加号
addAnswer() {
this.radioKey++;
// ...
},
// 减号
delAnswer(delIndex) {
this.radioKey++;
// ...
},
},
};
</script>
element-ui 文本域字体不一样
遇到问题:
发现其他表单组件字体和文本域字体不一样
解决办法:
这是原生textarea默认字体问题,所以需要增加.el-textarea__inner字体属性
.el-textarea__inner{
font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
}
element-ui的穿梭框数据量大时点击“全选”卡顿
遇到问题:
数据量小的时候问题还没有暴露,当数据大概有几千条时,点击全选时页面需要大概需要三四秒,单选、移动操作也是如此,对于用户来说体验感很差。
解决办法:
可以将node_modules\element-ui\packages\transfer组件拎出来作为组件,针对组件的方法进行改写,再进行引用。
- 修改transfer-panel.vue文件里的updateAllChecked() 全选方法:
updateAllChecked() {
/*
this.checkableData是对象数组,需要每个对象里的key
checkableDataKeys是'所有可以进行选择的item'的key的数组
*/
// const checkableDataKeys = this.checkableData.map(
// (item) => item[this.keyProp]
// );
/*
this.checked是'已经选中的item'的数组
如果this.checked存在着checkableDataKeys的每一项的话,那么every方法返回true
allChecked为是否全选,这里是O(n^2)的时间复杂度
*/
// this.allChecked =
// checkableDataKeys.length > 0 &&
// checkableDataKeys.every((item) => this.checked.indexOf(item) > -1);
// 修改
let checkObj = {};
/* 含义:如果this.checked=['a','b','c'],那么checkObj={a:true,b:true,c:true} */
this.checked.forEach((item) => {
checkObj[item] = true;
});
/*
含义:item[this.keyProp]为item对象中this.keyProp(属性)的属性值,
然后使用这个值作为checkObj的属性名来查找。遍历this.checkableData数组,
如果checkObj对象的所有对应属性都存在(即checkObj[item[this.keyProp]]为true),
那么every方法返回true
*/
this.allChecked =
this.checkableData.length > 0 &&
this.checked.length > 0 &&
this.checkableData.every((item) => checkObj[item[this.keyProp]]);
},
以及单选逻辑:
watch: {
checked(val, oldVal) {
this.updateAllChecked();
// 源码
// if (this.checkChangeByUser) {
// O(n^2)的时间复杂度
// const movedKeys = val.concat(oldVal).
// filter(v => val.indexOf(v) === -1 || oldVal.indexOf(v) === -1);
// this.$emit('checked-change', val, movedKeys);
// } else {
// this.$emit('checked-change', val);
// this.checkChangeByUser = true;
// }
// 修改
let newObj = {};
val.every((item) => {
newObj[item] = true;
});
let oldObj = {};
oldVal.every((item) => {
oldObj[item] = true;
});
if (this.checkChangeByUser) {
// O(n)
const movedKeys = val
.concat(oldVal)
.filter((v) => newObj[v] || oldVal[v]);
this.$emit("checked-change", val, movedKeys);
} else {
this.$emit("checked-change", val);
this.checkChangeByUser = true;
}
},
- 修改main.vue里的addToRight() 移动方法
addToRight() {
let currentValue = this.value.slice();
const itemsToBeMoved = [];
const key = this.props.key;
// 源码
// this.data.forEach(item => {
// const itemKey = item[key];
// O(n^2)
// if (
// this.leftChecked.indexOf(itemKey) > -1 && this.value.indexOf(itemKey) === -1
// ) {
// itemsToBeMoved.push(itemKey);
// }
// });
// 修改
let leftCheckedKeyPropsObj = {};
this.leftChecked.forEach((item) => {
leftCheckedKeyPropsObj[item] = true;
});
let valueKeyPropsObj = {};
this.value.forEach((item) => {
valueKeyPropsObj[item] = true;
});
this.data.forEach((item) => {
const itemKey = item[key];
// O(n)
if ( leftCheckedKeyPropsObj[itemKey] && !valueKeyPropsObj[itemKey]) {
itemsToBeMoved.push(itemKey);
}
});
currentValue = this.targetOrder === 'unshift'
? itemsToBeMoved.concat(currentValue)
: currentValue.concat(itemsToBeMoved);
this.$emit('input', currentValue);
this.$emit('change', currentValue, 'right', this.leftChecked);
}
除此之外,还要优化两个computed:
computed: {
sourceData() {
let valueObj = {};
this.value.forEach((item)=>{
valueObj[item] = true;
});
return this.data.filter(
(item) => !valueObj[item[this.props.key]]
);
},
targetData() {
if (this.targetOrder === 'original') {
let valueObj = {};
this.value.forEach((item)=>{
valueObj[item] = true;
});
let data = this.data.filter(
(item) => valueObj[item[this.props.key]]
);
return data;
} else {
return this.value.reduce((arr, cur) => {
const val = this.dataObj[cur];
if (val) {
arr.push(val);
}
return arr;
}, []);
}
}
}
Vant2 时间选择DatetimePicker,在配合弹出层时,默认的弹出高度过低,导致有时候没法滑动选择。(浏览器看不出来,手机上才能发现这个问题)
- 原因分析:可能是给弹出层设置了高度,设置到高度小于时间选择的高度,导致这个问题
- 解决方案:
<van-popup v-model="showNew" position="bottom" :style="{ height: '40%' }">
<van-datetime-picker @confirm="okConfirmNew" @cancel="falseCancel" v-model="currentDate" type="year-month"
title="选择月日" :min-date="minDateNew" :max-date="maxDateNew" :formatter="formatter" />
</van-popup>
Elment 表格出现横向滚动条导致fixed栏无法对齐
- 解决方案:
.el-table__fixed-body-wrapper {
.el-table__body {
padding-bottom: 15px;
}
}
在点击表格某一个单元格时,进行修改表格数据的时候表格绑定的值已经改了,但是页面上没有更新渲染上去。
- 解决方案:
editChange(value) {
this.$set(value, "editing", true);
},
使用this.$set
可以解决Vue响应式系统的一个限制,即无法检测到通过索引直接设置数组元素或通过Object.defineProperty添加的属性的变化,所以通过this.$set
方法,可以显式地告诉Vue,某个属性的值已经发生了变化,从而触发视图的更新。
在赋值中就尽量使用this.$set
进行赋值,少用this赋值。
form表单提交的时候如果给后台的数据和输入的数据不一样不要直接修改表单里的数据。如果直接修改表格里的数据保存没成功,form表单里的数据也会被更改。
-
例如:有个多选框绑定的是个数组,后台需要把多选的数组变成用逗号分隔的字符串。
-
解决方案:
this.form.executionTime = this.executionTimeList.join(“,”);
手机号校验写的太复杂,运营商新出的手机号校验不通过
const reg = /^1[3|4|5|7|8][0-9]\d{8}$/;
- 解决方案:
const reg = /^1\d{10}$/;
手机号校验不要写的太复杂,越复杂后期如果新出手机号代码就不兼容了。
Element input 原生属性,自动获取焦点(autofocus)在我放到表格对应每一个单元格时有时候不生效。
- 解决方案:
点击对应单元格后获取对应input,然后给他添加autofocus自动获取焦点(具体思路是这样,暂时没试过)
col出现错乱
-
前置条件:多个row
-
解决方法:在最近一个row上加
style=" display: flex;flex-wrap: wrap;"
el-date-picker,修改时,不显示修改后的值
- 解决:
@input="daterangeChange"
daterangeChange() {
this.$nextTick(() => {
this.$forceUpdate();
});
},
ruoyi页面开启缓存不生效问题
-
使用方法:保证路由和name值一致,并在菜单设置中开启缓存(默认开启)
-
name值需要大写(/system/menu/getRouter返回的是首字母大写的)
-
注意点:A页面输入搜索条件但未点击查询,再次进来A页面需要刷新数据,
beforeRouteEnter
-next
-vm
elementplus有的组件是英文(未使用ruoyi)
- 解决,在main.ts中加
locale:locale
select选择器,只显示key值不显示label
- 导致原因:list中值类型和v-model的值类型不一致
列表出现错乱,由于没有加key属性
-
场景:
-
item上有v-if判断,页面显示的顺序和代码顺序不一致
-
显示/隐藏列(有图片),会导致图片列内容显示在其他列中
-
弹窗中使用selection-change,中间变量(当前选项的id集合),渲染选中状态使用初始变量(已选完成的id集合)
-
场景:弹窗-select+弹窗-table复选,两个弹窗
-
问题:需要回显已选的ids,使用中间变量(操作数据),回显有问题,分页回显有时不成功
-
解决:不使用中间变量(this.chooseIds),使用初始变量(this.batchAddForm.serviceObjectIds)去toggleRowSelection渲染选中状态
-
注意点
-
需要中间变量
-
chooseIds代表,每次打开table弹窗,当前选项的id集合
-
this.batchAddForm.serviceObjectIds,代表,已选完成的id集合
-
selection-change 当选择项发生变化时会触发该事件
- 场景1:手动选中/取消复选框,会触发
- 场景2:切换分页,也表示当前选项发生变化,会触发(容易被忽视)
- 场景3:第二个弹窗关闭(组件隐藏),也会触发,并且这是selection是空数组
-
<!-- 选择服务对象 -->
<el-dialog
title="选择服务对象"
:visible.sync="showObjTable"
width="800px"
append-to-body
>
<el-table ref="multipleTable" row-key="serviceObjectId" :data="serviceTableData" @selection-change="handleSelectionChange" border stripe
:header-cell-style="{ background: 'rgba(238, 242, 246, 1)' }">
<el-table-column type="selection" reserve-selection width="55" align="center">
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="totalObj" :page.sync="queryObj.pageNum" :limit.sync="queryObj.pageSize"
@pagination="getObjList" />
<span slot="footer" class="dialog-footer">
<el-button @click="cancelChoose">取消</el-button>
<el-button type="primary" @click="submitChoose">确定</el-button>
</span>
</el-dialog>
// 选择服务对象
chooseObj() {
this.chooseIds=this.batchAddForm.serviceObjectIds
this.queryObj.pageSize=10
this.queryObj.pageNum=1
this.getObjList()
this.showObjTable=true
},
getObjList(){
getObjectPageList(this.queryObj).then((res) => {
this.serviceTableData = res.rows;
this.$nextTick(() => {
res.rows.forEach((row) => {
if (this.batchAddForm.serviceObjectIds.includes(row.serviceObjectId)) {
this.$refs.multipleTable.toggleRowSelection(row, true)
}
})
})
this.totalObj=res.total
});
},
// 多选框选中数据
handleSelectionChange(selection) {
this.chooseIds=Array.from(selection,x=>x.serviceObjectId)
},
submitChoose(){
this.batchAddForm.serviceObjectIds=this.chooseIds
this.showObjTable=false
this.resetChoose()
},
微信小程序
兼容性问题
- 头像无法正常显示(线上地址)
- 解决方法:加wx:if
- else判断下的标签中存在change事件中变量,iOS会显示该标签并显示实时change内容(Android不会出现)
- 解决方法:else改成if