element input 只能输入数字_【Element-Vue虐心记】从手贱多写一个分号开始去修改Element-Vue的源码...

40665b1f22648702cffc4aa8bef04376.png

8b24c5174d3e0a6867b614878489a890.png
Vincent van Gogh – Self-Portrait

因为手撸CSS的时间长了,所以在使用Element时会出现一些因为习惯而导致的错误。其中最大的遗留习惯就是写完样式之后加一个分号。

起因是最近的一个项目,用到了Vue,组件选的是Element,在用el-form或el-form-item组件时设置的标签宽度总是不生效,然后一检查发现是组件属性label-width设置时多写了一个分号。正确的是(label-width写在el-form上和el-form-item上都可以):

<el-form>
  <el-form-item label="姓名:" label-width="100px">
    <el-input placeholder="请输入姓名"></el-input>
  </el-form-item>
</el-form>

错误的是:

<el-form>
  <el-form-item label="姓名:" label-width="100px;">
    <el-input placeholder="请输入姓名"></el-input>
  </el-form-item>
</el-form>

这就是典型的CSS写多的后果,敲分号跟敲回车似的顺手。这个习惯还不容易纠正,所以,发现标签宽度不生效时不时就出现,次数多了,就毛了,于是一冲动去改源码了。

在没有看源码之前,我们可以大概猜测一下Element对于label-width设置的原理:我们设置这个属性并传值,组件检查到这个属性有值之后,就把这个宽度设置给标签。好吧,其实这段话跟废话一样,传的这个值最终肯定是设置给了标签啊,不然还能干嘛。所以重点是看源码是怎么实现的。

Github上有源码,下载之后搜索el-form可以找到相关的组件,文件名字叫form-item.vue,按照Vue的设定,驼峰写法的prop属性对应着短横线分隔的prop名,那么反过来,我们知道了label-width的prop名,找属性,肯定就是labelWidth了,果然,有。

props: {
  labelWidth: String,
}

那么这个属性的值是怎么获取的呢?肯定不是简单地取个值,里面涉及到一些判断,尤其是父节点的判断。主要思路就是先检查一下el-form-item的label-width属性,如果有就拿这个值,如果没有就看它爸(el-form)有没有label-width,它爸有就用它爸的这个属性值,最后把这个属性值赋值给width属性,组成一个JS对象返回,看这个方法名字,就知道这个对象是一个包含样式(Style)的对象。

labelStyle() {
  const ret = {};
  ...
  const labelWidth = this.labelWidth || this.form.labelWidth;
  if (labelWidth) {
    ret.width = labelWidth;
  }
  return ret;
}

那么,很自然的,这个组成的样式对象肯定要加在标签上了吧,是的。下面这个源码说明了它是通过动态绑定样式的方式给对应的标签设置了样式。

<label :for="labelFor" class="el-form-item__label" :style="labelStyle" v-if="label || $slots.label">
  <slot name="label">{{label + form.labelSuffix}}</slot>
</label>

到这里,就水落石出了,动态绑定样式的值是一个JS对象,JS对象里面的key就是width,value就是我们传的值,如果我们传"100px"那么一切安好,如果我们传"100px;"那这个value值就是错的,因为它不是一步到位拼接成一个"width:100px;",而是先变成一个JS对象然后再动态绑定做处理。

知道原因了,那优化就简单了。我们在上面获取值的步骤做个处理就好了。比如这样:

labelStyle() {
  ...
  if (labelWidth) {
    ret.width = labelWidth.substring(0,labelWidth.length - 1);
  }
  return ret;
}

看这个项目的package.json可以知道用npm run dist进行编译。我们可以使用的文件在/lib/index.js中。引用之后,发现,哎,我们写成"100px;"有效了,但标签和表单怎么依然不在一行呢。

12e5f768f9bf71d06f0d8ffbf7bb6960.png

原来,表单的样式设置了"relative",并且它本来应该有一个"margin-left",这个"margin-left"的值就是标签对应的"width"值,所以,在获取"label-width"值的时候,还有一个设置表单"margin-left"的地方。

好吧,继续找,仍然在同一个文件中,有下面这个方法,设置了一个内容样式,并且把这个内容样式加在了表单上。我们仍然是把设置"margin-left"的地方修改一下即可。

contentStyle() {
  const ret = {};
  if (labelWidth === 'auto') {
    ...
  } else {
    // ret.marginLeft = labelWidth;
    ret.marginLeft = labelWidth.substring(0,labelWidth.length - 1);
  }
  return ret;
}

这下子就可以了。

但是,如果我一个项目里只是偶尔会手贱不小心加了分号,大部分时候都遵纪守法,操作就是这么骚,怎么办?那就在需要修改的上面两处判断一下再修改即可:

if(labelWidth.substring(labelWidth.length - 1) == ";"){
  ret.width = labelWidth.substring(0,labelWidth.length - 1);
}else{
  ret.width = labelWidth;
}

以及:

if(labelWidth.substring(labelWidth.length - 1) == ";"){
  ret.marginLeft = labelWidth.substring(0,labelWidth.length - 1);
}else{
  ret.marginLeft = labelWidth;
}

编译,引用。至此,随便加不加分号,都OK了。

要不要用在项目里?呵呵哒,还是慢慢改习惯吧。

再见。

826c926064b0478ecea57e3315a873e7.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值