为element-ui 打个补丁修复el-form的label width问题

为element-ui 打个补丁修复el-form的label width问题

问题回顾

用 element-ui 遇到一个奇怪的问题,控制台老是抛错

[Vue warn]: Error in beforeDestroy hook: "Error: (ElementForm]unpected width

最终排查下来是 el-form 设置了 label-width="auto" 然后又处于不展示的情况下(display: none,项目里是 el-tab产生的)在离开页面的时候就会有问题。

el-form 在挂载时(display:none也会挂载),会初始化一个 el-label 的 width 的数组,在销毁的时候时候会依次清除 该数组 。问题原因在此获取宽度函数上

// https://github.com/ElemeFE/element/blob/dev/packages/form/src/label-wrap.vue#L32
methods: {
    getLabelWidth: function getLabelWidth() {
      if (this.$el && this.$el.firstElementChild) {
        var computedWidth = window.getComputedStyle(this.$el.firstElementChild).width;
        // return computedWidth == 'auto' ? 'auto' : Math.ceil(parseFloat(computedWidth));
        return Math.ceil(parseFloat(computedWidth));
      } else {
        return 0;
      }
    },
    //...
}

在注册的时候取宽度(getLabelWidth)会拿到 NaN,因为 getComputedStyle 在元素未实际渲染时(父元素display:none)会取到 auto, parseFloat('auto') 就会NaN,不会被注册到 数组 potentialLabelWidthArr

// https://github.com/ElemeFE/element/blob/dev/packages/form/src/form.vue#L168
registerLabelWidth(val, oldVal) {
  if (val && oldVal) {
     const index = this.getLabelWidthIndex(oldVal);
     this.potentialLabelWidthArr.splice(index, 1, val);
   } else if (val) {
     this.potentialLabelWidthArr.push(val);
   }
}

在销毁的时候自然取不到 就抛错了 [ElementForm]unpected width

// https://github.com/ElemeFE/element/blob/dev/packages/form/src/form.vue#L160
getLabelWidthIndex(width) {
  const index = this.potentialLabelWidthArr.indexOf(width);
    // it's impossible
    if (index === -1) {
    throw new Error('[ElementForm]unpected width ', width);
  }
  return index;
},

原因找到了,更改也比较简单, getLabelWidth 函数中 针对auto做个处理

// lib/element-ui.common.js
getLabelWidth: function getLabelWidth() {
   if (this.$el && this.$el.firstElementChild) {
     var computedWidth = window.getComputedStyle(this.$el.firstElementChild).width;
     return computedWidth == 'auto' ? 'auto' : Math.ceil(parseFloat(computedWidth));
     // return Math.ceil(parseFloat(computedWidth));
   } else {
     return 0;
   }
 },

想在项目中应用该更新,可以为该项目提个pr,不过现在700+issue, 而且合并太慢了;还有方式就给element-ui弄到本地,改了代码打包本地引用。patch就有点像第二种方式,提供命令而不是去操作文件为你的依赖包应用上自己的更新。

patch

pnpm

pnpm 自定义支持 patch 命令

pnpm patch <package@version>
# 此时应该给你源码copy出来一份了,接着打开它提示的文件更改源码(zsh 支持 open打开),然后提交
# 需要注意的是要改对文件!!(本次我改的是 lib/element-ui.common.js),结合错误抛出位置和 package.json 的 main
pnpm patch-commit <path>

实际场景:

➜  vue2_65 git:(main)pnpm patch element-ui@2.15.14
You can now edit the following folder: /private/var/folders/sb/hl7wb2_s1mg2_6ncfs8zwl1c0000gn/T/adaf3ade4d5d95518a629b519ce2f5ef

Once you're done with your changes, run "pnpm patch-commit /private/var/folders/sb/hl7wb2_s1mg2_6ncfs8zwl1c0000gn/T/adaf3ade4d5d95518a629b519ce2f5ef"
➜  vue2_65 git:(main)open /private/var/folders/sb/hl7wb2_s1mg2_6ncfs8zwl1c0000gn/T/adaf3ade4d5d95518a629b519ce2f5ef
➜  vue2_65 git:(main)pnpm patch-commit /private/var/folders/sb/hl7wb2_s1mg2_6ncfs8zwl1c0000gn/T/adaf3ade4d5d95518a629b519ce2f5ef
 WARN  deprecated vue@2.7.16: Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.
 WARN  8 deprecated subdependencies found: abab@2.0.6, core-js@2.6.12, domexception@4.0.0, glob@7.2.3, inflight@1.0.6, rimraf@2.7.1, rimraf@3.0.2, sourcemap-codec@1.4.8
Packages: -1
-
Progress: resolved 496, reused 476, downloaded 0, added 1, done

yarn

yarn 2 也支持patch(https://yarnpkg.com/cli/patch)

1.x 的话需要 安装 patch-packagepostinstall-postinstall

yarn add -S patch-package postinstall-postinstall

package.json 配置

"scripts": {
    "postinstall": "patch-package"
  },

接着更改源码 注意查看 依赖包的入口文件,确保改对文件

# 保存之后就打补丁,不要加版本号,不支持
yarn patch-package element-ui

建议重新装一遍依赖,后面每次装依赖都会有提示patches

...
success Saved lockfile.
$ patch-package
patch-package 8.0.0
Applying patches...
element-ui@2.15.14 ✔
✨  Done in 12.03s.

最后

打完补丁后都会产生 /patches 文件,pnpm 打完补丁还会再package.json下产生

"pnpm": {
    "patchedDependencies": {
      "element-ui@2.15.14": "patches/element-ui@2.15.14.patch"
    }
  }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值