问题缘由
近日需要开发一个双列的表单编辑页面,伪页面如下:
简单思索后决定使用el-col控制表单项宽度以达到双列的效果
问题出现
由于难度不大,三下五除二就搞定了,代码如下:
<el-form :model="edit.data" label-width="100px">
<el-col :span="12">
<el-form-item prop="name" label="用户名: ">
<el-input v-model="edit.data.name" placeholder="请输入用户名"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="type" label="账户类型: ">
<el-select v-model="edit.data.type" placeholder="请选择账户类型" style="width: 100%;">
<el-option v-for="(item,index) in dict.types" :key="index" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-form-item prop="remark" label="备注: ">
<el-input type="textarea" v-model="edit.data.remark" placeholder="请输入备注信息"></el-input>
</el-form-item>
</el-form>
[嘴角疯狂上扬] 然鹅,就在此时,问题出现了, 用户名输入框和账号类型下拉项无法点击的问题
具体大家可以到 el-form-item因el-col布局引起的部分表单项无法点击的问题的第一个表单中体验下
问题解决
- 首先通过百度找到了如下解决方案:vue+element UI中布局组件el-col和表单组件el-form组合使用时表单无法获取焦点
但是这里只说不能混用,那么真的不能混用吗?原因到底是为什么呢?
首先,通过浏览器控制台调试,发现将el-col的float:left样式取消后就正常了,如下图:
然鹅,这样虽说解决了不能点击的问题,但是一个表单项就占了一行,显然是不符合需求的,于是自作聪明,添加了如下样式:
.el-col {
float: none;
display: inline-block;
}
嗯…问题解决了,但是这样的解决方案也不太优雅
继续找问题原因,当时写了这样一个表单,发现表单项是可以正常的点击的:
<el-form :model="edit.data" label-width="100px">
<el-col :span="12">
<el-form-item prop="name" label="用户名: ">
<el-input v-model="edit.data.name" placeholder="请输入用户名"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="type" label="账户类型: ">
<el-select v-model="edit.data.type" placeholder="请选择账户类型" style="width: 100%;">
<el-option v-for="(item,index) in dict.types" :key="index" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-form>
这和上面的表单不就差了一个字段吗?为什么加上remark的表单项之后就不行了呢?
比较两段代码,发现name和type的表单项的级次是三级,而remark的表单项的级次是二级,那么问题是不是出在了dom的层次结构上呢?
有此想法,在remark表单项外层加了个el-col,发现可以正常点击了,伪代码如下:
<el-form :model="edit.data" label-width="100px">
<el-col :span="12">
<el-form-item prop="name" label="用户名: ">
<el-input v-model="edit.data.name" placeholder="请输入用户名"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="name" label="账户类型: ">
<el-select v-model="edit.data.type" placeholder="请选择账户类型" style="width: 100%;">
<el-option v-for="(item,index) in dict.types" :key="index" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col>
<el-form-item prop="remark" label="备注: ">
<el-input type="textarea" v-model="edit.data.remark" placeholder="请输入备注信息"></el-input>
</el-form-item>
</el-col>
</el-form>
至此,问题成功解决
问题原理
带着问题,我们找一找源码,在el-form-item.vue的代码中发现了这样一个计算属性:
form() {
let parent = this.$parent;
let parentName = parent.$options.componentName;
while (parentName !== 'ElForm') {
if (parentName === 'ElFormItem') {
this.isNested = true;
}
parent = parent.$parent;
parentName = parent.$options.componentName;
}
return parent;
},
这里通过当前组件,一级一级向上找,直到找到el-form组件就返回,而其他计算属性/方法依赖form计算属性,这也就能解释为什么remark表单项能正常点击,而name和type表单项无法点击的问题了。
总结
el-form下的el-form-item的dom级次务必一致,如有不一致的情况会导致表单项无法点击的问题