[ElemeFE/element][Bug Report] Cascader 级联选择器连续多次点击浏览器卡死

2023-12-08 868 views
7

Element UI version

2.11.1

OS/Browsers version

win10/chrome 103版本64 位

Vue version

2.3.3

Reproduction Link

https://codepen.io/517399251/pen/bGvgvqB?editors=1100

Steps to reproduce

连续多次的点击多选可搜索的示例,界面会出现卡死的现象,cpu占用超过100%

What is Expected?

浏览器界面不卡死

What is actually happening?

界面卡死无法操作

回答

7

我也出现了这个问题 ,我的element 版本是 2.13.2,多次选择后浏览器渲染进程卡住,cpu占用到100,其他tab不受影响。我的chrome是104

6

我的也出现了浏览器卡死现象,但无法稳定复现 element-ui: 2.13.2 chome: 104.0.5112.79

2

我的是层级比较深时浏览器卡死,但是无法稳定复现 element-ui:2.11.0

0

经过测试,是chrome104版本比较容易重现。但是也只有部分的用户会出现。不是全部用户都能重现, 原因是使用了 aria-owns 属性,我在最新的测试中,删除了.el-cascader-node节点的这个属性,能解决这个问题

9

我的也出现了,快速多次点击展开然后失焦! element-ui: 2.14.1,chome: 104.0.5112.82

6

我也遇到了,还以为是数据量太大,但是数据少量的时候也会出现; element-ui: 2.13.2版本,chrome 104.0.5112.102

0

我这边也遇到了类似的问题,按照这个方式解决了,但不清楚具体的原因,能解释一下么? @luomu172

2

@zeelq 您好,能说下具体实现细节吗?我尝试把"el-cascader-node": false 置为false发现有样式问题以及change事件总是选到最后一个! 更改图片:20220823162953.png

8

@zeelq 您好,能说下具体实现细节吗?我尝试把"el-cascader-node": false 置为false发现有样式问题以及change事件总是选到最后一个! 更改图片:20220823162953.png

我是参考了 @luomu172 提供的解决思路,通过操作dom方式解决的,没更改组件源码,你可以参考下: const $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]'); Array.from($el).map(item => item.removeAttribute("aria-owns"))

在Cascader组件的.el-cascader-node 元素生成后移除aria-owns属性。

2

mdn查看这个属性,是给渲染提供关系指导。具体为什么会卡死,和浏览器对这块的实现有关系,如果在深入 的话,需要去看浏览器的实现原理,这块我了解不足,所以无法告知你具体的原理。有兴趣的话,你可以在深挖一下,如有结论,希望能告知我一下

5

这个问题很严重啊 我这边是一直稳定出现,无论数据有几个都会出现 就是官方的demo

5

在win10系统chrome/edge,在编辑/新增几次后稳定出现卡顿问题,mac就不会出现该问题 一些自己的原因导致element-ui不好升级版本,头痛

5

在Cascader组件的.el-cascader-node 元素生成后移除aria-owns属性。 请问如何知道.el-cascader-node生成了? 我遇到的一个情况为只有个别人点击级联选择器就会导致页面崩溃,但是其他人使用起来正常,想请教下 const $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]'); Array.from($el).map(item => item.removeAttribute("aria-owns")); 这两行代码在什么情况下运行?我不知道在什么样的情况下使用这个方法,换句话说,这个应该需要一个函数触发吧,就像@click函数这样触发,能写个demo吗 ———————————— 另一个issue上给我的回答是在mounted上运行,但是我的理解是此时级联选择器子节点还没有出现,应该拿不到el-cascader-panel .el-cascader-node这个节点吧

这是他的代码 mounted () { const $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]'); Array.from($el).map(item => item.removeAttribute("aria-owns")); };

我在mounted中打印console.log($el)是这样的结果 image 使用的vue版本是3.1.2 element-plus版本是1.0.2-beta.52

0

可以试试在 option赋值以后

this.$nextTick(() => { // 添加这段代码 const $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]'); Array.from($el).map(item => item.removeAttribute("aria-owns")); })

6

我参考了上述方法,可以在main.js 文件直接监听 dom 处理。所有组件都生效,可以不用再去组件中处理了。 如果怕污染全局变量,可以包裹在一个函数中执行。

var observer = new MutationObserver(function (mutations, observer) {
    mutations.forEach(function (mutation) {
        mutation.addedNodes.forEach(node => {
            if (node.nodeType === 1) {
                const $el = node.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]'); Array.from($el).map(item => item.removeAttribute('aria-owns'))
            }
        })
    })
})
observer.observe(document.body, {
    characterData: false,
    childList: true,
    attributes: false,
    subtree: true
})
6

测试了一下 可在级联框绑定的@change事件中添加 handlChange(value) { // 修复级联选择器连续多次点击浏览器卡死 cpu占用超过100%bug const $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]'); Array.from($el).map(item => item.removeAttribute("aria-owns")); }

7

我只是用了最基本的联级组件,数据量也不大,部分用户频繁点击几下就会卡死且稳定复现,cpu占用超过100%,页面无响应

0

谢谢,我们项目组有额外封装,在 CascasderPanel 显示出来的时候,将DOM中元素处理掉就好了

3

目前发现Mac系统的Chrome必现,win的还好,但是CPU确实飙高。 飙高的情况再我的笔记本上必现,由于组件开启了搜索过滤,直接点击右侧下拉有几率不stuck,只要点击搜索部分必然stuck,CPU1 100% 临时解决方案

@visible-change="e => cascaderVisable(e, item)"

cascaderVisable (e, item) {
  // 根据ElementUI的BUG提示  https://github.com/ElemeFE/element/issues/22060
  const $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]')
  Array.from($el).map(item => item.removeAttribute('aria-owns'))
  if (item.visible !== undefined && item.visibleChange) {
    item.visibleChange(e)
  }
},

环境

chrome:版本 109.0.5414.119(正式版本) (arm64) 系统企业微信截图_3953c206-76fe-4b86-8103-753631466064

8

您好,想请问一下这个具体是怎么处理的呀,目前使用上述的这个方法还是解决不了问题@IvanChen008

4

您好,你使用了这个方法就不会出现卡顿现象了吗,我使用同样的方法但是客户的电脑卡顿任然出现,我和客户使用的都是Chrome109.0.5414.120版本,我的电脑从来都没出现卡顿现象。远程连接客户的电脑,只有一点击级联选择的input就会出现卡顿

8

@YihaoCCC @sanfenredu cascader的级联元素是点击后才加载的,所以监听change方法不怎么管用。可以参考我的方法

4

再给大家提供一种自己项目的修复思路,由于使用的地方实在太多了,所以在项目中换了一种方案

  1. 重新定义一个组件ElCascaderFixed.vue
    
    <script>
    import {
    Cascader
    } from 'element-ui'
    import elfix from '@/components/global/el-cascader-fixer'

export default { extends: Cascader, name: 'ElCascader', mounted () { this.$on('visible-change', elfix) } }


2. 在组件引用的时候替换成这个新的组件

// 去掉原来的element-ui中的Cascader引用 import { ... // Cascader, ... } from 'element-ui' import Cascader from '@/components/global/ElCascaderFixed'

Vue.use(Cascader)



> PS:补充一下`.el-scrollbar`这个样式在组件集成之后被未被展示,应该是样式隔离的问题,可以自己在补全下,否则会出现滚动条
4

请问import elfix from '@/components/global/el-cascader-fixer'的el-cascader-fixer内容是什么?

1

就是ElCascaderFixed.vue这个,写在reply里了

7

有2个时机可以触发这段代码:①watch options属性有值时;②组件的@expand-change事件触发时。 记得放到nextTick内执行,保证运行的时候.el-cascader-node节点已经生成了。

4

Chrome 105.0.5195.54 Element 2.13.0 仍存在此bug 笔记本稳定触发 借用楼上 @RandyZ 的代码 直接放在一个cascaderFix.vue文件里了 应该可以直接cv去用了

@/components/cascaderFix.vue

<script>
import { Cascader } from "element-ui";

function cascaderVisable(e, item) {
  const $el = document.querySelectorAll(
    ".el-cascader-panel .el-cascader-node[aria-owns]"
  );
  Array.from($el).map((item) => item.removeAttribute("aria-owns"));
  if (item && item.visible !== undefined && item.visibleChange) {
    item.visibleChange(e);
  }
}

export default {
  extends: Cascader,
  name: "CascaderFix",
  mounted() {
    this.$on("visible-change", cascaderVisable);
  },
};
</script>
<style lang="less">
.el-scrollbar {
  overflow: hidden;
  position: relative;
}
</style>

用法

import CascaderFix from "@/components/cascaderFix.vue";
//省略
components: {
  CascaderFix,
}
8
Vue.component('el-cascader', {
  extends: Cascader,
  name: 'CascaderFix',
  methods: {
    fixCascaderAriaOwns(e, item) {
      const $el = document.querySelectorAll(
        '.el-cascader-panel .el-cascader-node[aria-owns]'
      );
      Array.from($el).map((item) => item.removeAttribute('aria-owns'));
      if (item && item.visible !== undefined) {
        if (item.visibleChange) {
          item.visibleChange(e);
        }
        if (item.expandChange) {
          item.expandChange(e);
        }
      }
    },
  },
  mounted() {
    this.$on('visible-change', function (...args) {
      this.$nextTick(() => {
        this.fixCascaderAriaOwns(...args)
      }) 
    });
    this.$on('expand-change', function (...args) {
      this.$nextTick(() => {
        this.fixCascaderAriaOwns(...args)
      }) 
    });
  },
});