目录
1.1 使用 el-form 表单校验规则,无法对 number 类型输入框校验
1.2 隐藏后重新显示的 el-input 无法自动获得焦点(双击实现输入框编辑)
2.1 解决 el-table 某列内容长度超过列宽,默认换行问题
2.3 实现 el-table 隔行变色(ts 数据类型定义)
1. el-form 表单相关问题
1.1 使用 el-form 表单校验规则,无法对 number 类型输入框校验
<el-form :rules="rules" :model="scheduleFormLabel">
<el-form-item label="活动人数:" required prop="peopleNum">
<el-input
type="number"
placeholder="请输入活动人数"
v-model="scheduleFormLabel.peopleNum"
/>
<template #suffix>
<span class="t-white t-f12">人</span>
</template>
</el-input>
</el-form-item>
</el-form>
rules: {
peopleNum: [
{
required: true, message: '', trigger: 'blur',
},
{
type: 'number',
min: 1,
max: 100000,
message: '活动人数应该在1-100000之间',
trigger: 'blur',
},
],
},
解决方案:给 v-model 加上 .number 即可
<el-input v-model.number="scheduleFormLabel.peopleNum"></el-input>
1.2 隐藏后重新显示的 el-input 无法自动获得焦点(双击实现输入框编辑)
需求:这有一个菜单树,双击菜单项文本后,编辑菜单项名称
实现逻辑:
- 双击菜单文本时,会触发方法 @dblclick=”handleDoubleClickMenuText()” ,该方法记录当前点击的菜单项id,并触发视图更新(当前菜单项id为记录的菜单id时,就会展示输入框,隐藏文本)
- 通过设置 ref 变量,让输入框获得焦点 menuItemTextInputRef.value.focus(); 输入框实际却没获得
<template>
<el-tree
node-key="id"
:props="propsMap"
:data="state.data"
>
<template #default=" {node, data} ">
<span>
<!-- 节点文本 -->
<span
v-show="state.operateMenuItemId !== data.id"
@dblclick="handleDoubleClickMenuText(data.id, data.id)"
>
{{node.label}}
</span>
<!-- 编辑节点文本的输入框 仅在双击文本的时候展示 -->
<el-input
v-model="data.label"
v-show="state.operateMenuItemId === data.id"
ref="menuItemTextInputRef"
@blur="handleDoubleClickMenuText('', data.id)"
/>
</span>
</template>
</el-tree>
</template>
<script lang="ts" setup>
import {
reactive,
ref,
} from 'vue';
import { MenuTreeData } from '@/types/common/menu-tree';
import { ElInput } from 'element-plus';
// 配置选项的映射
const propsMap = {
children: 'children',
label: 'label',
};
const state = reactive({
// 树形菜单数据
data: [
{
id: 'a1',
label: '菜单1',
children: [
{
id: 'aa1',
label: '菜单1.1',
},
{
id: 'ab1',
label: '菜单1.2',
children: [
{
id: 'aba1',
label: '菜单1.2.1',
},
],
},
],
},
{
id: 'b1',
label: '菜单2',
},
//...
] as MenuTreeData[],
// 当前操作的菜单项的id
operateMenuItemId: '',
});
// 菜单项文本输入框DOM
const menuItemTextInputRef = ref();
/**
* 处理双击菜单项文本
* @param id - 菜单项id
*/
function handleDoubleClickMenuText(id: string) {
state.operateMenuItemId = id;
if (menuItemTextInputRef.value) {
menuItemTextInputRef.value.focus();
}
}
</script>
原因分析:
- 渲染页面时,随着el-tree节点的遍历,会渲染多个el-input节点(因为使用了 v-show,节点存在,只是看不见)
- 也就是说,页面里有多个 el-input,ref 被赋值了很多次,最终值是最后的一个el-input(果然,双击最后一个菜单项文本时,输入框获取到了焦点)
问题解决:
为了确保 el-input 只渲染一次(只存在一个有 ref=”menuItemTextInputRef” 属性的 el-input),应该采用 v-if 替代 v-show
<template>
<el-tree
node-key="id"
:props="propsMap"
:data="state.data"
>
<template #default=" {node, data} ">
<span>
<!-- 节点文本 -->
<span
v-if="state.operateMenuItemId !== data.id"
@dblclick="handleDoubleClickMenuText(data.id, data.id)"
>
{{node.label}}
</span>
<!-- 编辑节点文本的输入框 仅在双击文本的时候展示 -->
<el-input
v-model="data.label"
v-else
ref="menuItemTextInputRef"
@blur="handleDoubleClickMenuText('', data.id)"
/>
</span>
</template>
</el-tree>
</template>
拓展:
- 页面上本来没有 el-input 这个DOM,只有双击后,更新了当前选中的菜单ID(state.operateMenuItemId) ,才能触发 DOM 更新;
- DOM更新完成之后,才能获取 el-input 的焦点
(也就是说,获取焦点这一步,应该稍微等一下,等 DOM 更新了,el-input 加载出来了,才能获取焦点);
因此,采用 setTimeout 来延迟执行获取输入框焦点的代码;
function handleDoubleClickMenuText(id: string) { state.operateMenuItemId = id; setTimeout(() => { if (menuItemTextInputRef.value) { menuItemTextInputRef.value.focus(); } }); }
2. el-table 表格相关问题
2.1 解决 el-table 某列内容长度超过列宽,默认换行问题
如图所示,非理想效果:
理想效果其实是:不换行,溢出隐藏,鼠标滑上去后有 tooltip 进行提示
实现方法:
<el-table-column
v-for="(item, index) in header"
:key="index"
:class-name="'table-cell'"
:show-overflow-tooltip="true"
:label="item.title"
:prop="item.key"
/>
// 可以在全局 SCSS 中添加,也可以单独加在页面当中
.el-tooltip__popper {
max-width: 800px;
background-color: red!important;
}
注意:
不能在 <style scoped></style> 中修改 ElementPlus 样式,不会生效
show-overflow-tooltip 属性需要谨慎使用,多列使用会影响页面加载速度
2.2 el-table 滚动条导致的行对不齐问题
如下图所示,左侧列固定,右侧列可以横向滚动,如果添加了滚动条,就会出现一行对不齐的情况
在行对齐的情况下,修改滚动条样式的解决方案:
给 el-table 添加属性 height=”300px”
在全局公共样式 .scss 中,添加设置:
::-webkit-scrollbar {
width: 10px; // 纵向滚动条的宽度
height: 10px; // 横向滚动条的高度
}
在自定义滚动条的页面或组件中,重新定义 ::-webkit-scrollbar 属性
2.3 实现 el-table 隔行变色(ts 数据类型定义)
如下图所示,直接解构参数会导致 ts 报错,缺少数据类型接口
interface changeRowParameter {
row?: number; // 行
column?: number; // 列
rowIndex: number; // 行下标
columnIndex?: number; // 列下标
}
/**
* 间隔行颜色
*/
const changeRow = ({ rowIndex }: changeRowParameter) => {
if (rowIndex % 2 === 0) {
// 奇数行背景色
return props.cStyle.rowContent;
}
// 偶数行背景色
return props.cStyle.wrapperContent;
};
3. el-popover 组件内部添加注释导致的问题
如下代码所示,看起来似乎没有问题,却出现了报错
<el-popover
ref="popover1"
placement="bottom-start"
width="213"
trigger="click"
:show-arrow="false"
popper-class="reset-tool-popover"
:disabled="disable"
v-model:visible="visible"
>
<template #reference>
<!-- 属性文本 -->
<span class="label" @click="handleClick">{{ label }}</span>
</template>
<div class="reset-box">
<div class="reset-button-wrapper" v-if="reset">
<!-- 重置按钮 -->
<div class="reset-button" @click="handleReset">
<div class="reset-left">
<img src="@/assets/images/design/settings/reset.svg" alt="" />
<span class="reset-action">Reset</span>
</div>
<span class="reset-shortcut">Alt + click</span>
</div>
</div>
<!-- 重置说明 -->
<p class="reset-explain">{{ explain }}</p>
<div class="reset-button-wrapper global-explain" v-if="isGlobal">
<img src="@/assets/images/design/settings/all-pages.svg" />
<span class="global-explain-text">Body (All Pages)</span>
</div>
</div>
</el-popover>
报错内容:Uncaught (in promise) ElementPlusError: [renderTrigger] trigger expects single rooted node…
报错原因:
根据提示可得,el-popover 希望只有一个根节点
<div class=”reset-box”> 作为内容区,只有一个DOM元素,不会导致报错
<template #reference> 作为插槽,不仅包含了一个DOM,还包含了一条注释
综上,使用 el-popover 时,在插槽里一定 “不能 ”使用注释