element-plus 工作经验总结

Element-plus

文章目录

  • Element-plus
    • [忠告: 最好锁定版本, 免得更新更出 BUG 来了](#忠告: 最好锁定版本, 免得更新更出 BUG 来了)
    • [el-drawer 设置 modal="false" 后, 遮罩元素仍存在, 点不了空白的地方](#el-drawer 设置 modal="false" 后, 遮罩元素仍存在, 点不了空白的地方)
    • [el-tree 大数据量时接收 check-change 事件报错导致涉及多个节点的操作没执行完毕](#el-tree 大数据量时接收 check-change 事件报错导致涉及多个节点的操作没执行完毕)
    • [el-table 表头 show-overflow-tooltip 无效解决办法 / 设置 class 控制全局超长隐藏, 以 el-tooltip 显示全部内容](#el-table 表头 show-overflow-tooltip 无效解决办法 / 设置 class 控制全局超长隐藏, 以 el-tooltip 显示全部内容)

忠告: 最好锁定版本, 免得更新更出 BUG 来了

遇到两次了, 没锁定 element-plus 版本, 打包后样式乱了, 逻辑变了...

el-drawer 设置 modal="false" 后, 遮罩元素仍存在, 点不了空白的地方

有两个思路:

  1. 通过 modal-class 把遮罩层样式改了, 让它只是看起来不显示, 这样 close-on-click-modal 应该能生效
    这个方案改动小, 但是满足不了产品需求 --- "点击其他表格行时, 可切换侧滑页内容", 于是引入 vueuse 的 onClickOutside 做了方案 2
  2. 方案2, 步骤如下:
    1. 给 drawer 和 modal 加上 pointer-events 相关 class , 让点击可以穿透遮罩层
    2. 使用 onClickOutside, 传入 handler 函数关闭 drawer , 传入 options.ignore , 指定忽略表格行(侧滑页的入口元素)的 css 选择器
    3. 如果 drawer 内部有弹框, 可以加上弹框遮罩的 class 选择器, 避免点击弹框时把 drawer 也关了

el-tree 大数据量时接收 check-change 事件报错导致涉及多个节点的操作没执行完毕

背景:

数据量大的时候(选中一个底下有很多子级的节点)check-change 事件不断触发, 到了 100 出头时, 接收事件处理的方法就一直报错了(发版后不报错, 但逻辑同样受影响), 不会处理后续逻辑了

定位:

本地运行开发环境里有报错, 错误信息里说的是数据更新影响到渲染了, 那就减少相关操作吧

解决

于是在接收处首先 await nextTick() 一下, 攒够一波了一起执行后续逻辑 -> 更新数据 -> 视图更新

如果之后还有问题, 那再整 setTimeout , 队列之类的吧, 或者干脆不用 check-change 事件了

el-table 表头 show-overflow-tooltip 无效解决办法 / 设置 class 控制全局超长隐藏, 以 el-tooltip 显示全部内容

背景:

UI 要求表头也要超长隐藏, 鼠标移入 tooltip 显示全局内容

思路:

之前的项目是用 render-header 实现的, 新项目用 render-heade 少, 觉得逐个表格写 render-header 控制显隐/ title 属性太麻烦, 于是复制 element-plus 的 show-overflow-tooltip 部分相关代码, 实现设置 class "showOverflowTooltip" 即可超长显示 tooltip (设置 class 就行, 跟表格没关系, 普通 div 设置了也能显示), 原理为 --- 全局监听 .showOverflowTooltip mouseover , 以虚拟 ref 显示全局 el-tooltip ,

具体代码

vue 复制代码
// APP.VUE

<template>
	<!-- ... -->

    <!-- 全局 tooltip -->
    <el-tooltip
        v-model:visible="visible"
        :content="content"
        placement="top-start"
        effect="dark"
        trigger="hover"
        :show-after="500"
        virtual-triggering
        :virtual-ref="triggerRef"
    ></el-tooltip>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { checkIsOverflow } from 'src/utils/dom.js';
    
// ...

// 全局, 以虚拟 ref 触发指定 class (.showOverflowTooltip) 鼠标移入显示 overflow tooltip
// 手动控制显隐(暂时没用到)
const visible = ref(false);
// tooltip 内容
const content = ref('');
// 虚拟 ref 指定 DOM
const triggerRef = ref(null);
// 全局监听 mouseover 鼠标移入, 控制虚拟 ref
const globalOnMouseOver = e => {
    const targetEl = e.target;
    // 鼠标移入的元素包含特定 class + 内容超出, 则设置虚拟 ref + content (popper 以 trigger: hover 显示)
    if (targetEl.classList.contains('showOverflowTooltip') && checkIsOverflow(targetEl)) {
        content.value = targetEl.innerText || targetEl.textContent;
        triggerRef.value = targetEl;
    }
};

// 添加事件监听
onMounted(() => {
    document.getElementById('vue应用根元素id').addEventListener('mouseover', globalOnMouseOver);
});

// 移除事件监听
onBeforeUnmount(() => {
    document.getElementById('vue应用根元素id').removeEventListener('mouseover', globalOnMouseOver);
});
</script>

<style lang="scss">
    .showOverflowTooltip, .showOverflowTooltip > * {
        max-width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
</style>
js 复制代码
// src/utils/dom.js

// 判断是否 text-overflow
// 参考 element-plus : https://github.com/element-plus/element-plus/blob/dev/packages/components/table/src/table-body/render-helper.ts
export const checkIsOverflow = (el) => {
    // use range width instead of scrollWidth to determine whether the text is overflowing
    // to address a potential FireFox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1074543#c3
    const range = document.createRange();
    range.setStart(el, 0);
    range.setEnd(el, el.childNodes.length);
    /** detail: https://github.com/element-plus/element-plus/issues/10790
     *  What went wrong?
     *  UI > Browser > Zoom, In Blink/WebKit, getBoundingClientRect() sometimes returns inexact values, probably due to lost precision during internal calculations. In the example above:
     *    - Expected: 188
     *    - Actual: 188.00000762939453
     */
    let { width: rangeWidth, height: rangeHeight } = range.getBoundingClientRect();
    const offsetWidth = rangeWidth - Math.floor(rangeWidth);
    const { width: cellChildWidth, height: cellChildHeight } = el.getBoundingClientRect();
    if (offsetWidth < 0.001) {
        rangeWidth = Math.floor(rangeWidth);
    }
    const offsetHeight = rangeHeight - Math.floor(rangeHeight);
    if (offsetHeight < 0.001) {
        rangeHeight = Math.floor(rangeHeight);
    }

    const { top, left, right, bottom } = getPadding(el);
    const horizontalPadding = left + right;
    const verticalPadding = top + bottom;
    if (
        rangeWidth + horizontalPadding > cellChildWidth ||
        rangeHeight + verticalPadding > cellChildHeight ||
        el.scrollWidth > cellChildWidth
    ) {
        return true;
    }

    return false;
};
// 获取 el padding
export const getPadding = (el) => {
    const style = window.getComputedStyle(el, null);
    const paddingLeft = Number.parseInt(style.paddingLeft, 10) || 0;
    const paddingRight = Number.parseInt(style.paddingRight, 10) || 0;
    const paddingTop = Number.parseInt(style.paddingTop, 10) || 0;
    const paddingBottom = Number.parseInt(style.paddingBottom, 10) || 0;
    return {
        left: paddingLeft,
        right: paddingRight,
        top: paddingTop,
        bottom: paddingBottom
    };
};

export default {
    checkIsOverflow,
    getPadding
};
相关推荐
loey_ln17 分钟前
webpack配置和打包性能优化
前端·webpack·性能优化
建群新人小猿18 分钟前
会员等级经验问题
android·开发语言·前端·javascript·php
爱上语文19 分钟前
HTML和CSS 表单、表格练习
前端·css·html
djk888829 分钟前
Layui Table 行号
前端·javascript·layui
NightCyberpunk1 小时前
HTML、CSS
前端·css·html
大霞上仙1 小时前
element ui table 每行不同状态
vue.js·ui·elementui
xcLeigh1 小时前
HTML5超酷响应式视频背景动画特效(六种风格,附源码)
前端·音视频·html5
zhenryx1 小时前
前端-react(class组件和Hooks)
前端·react.js·前端框架
lv程序媛1 小时前
el-table表头前几列固定,后面几列根据接口返回的值不同展示不同
javascript·vue.js·elementui