这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
前言
本篇问题记录element ui使用过程中的通用问题,具体某个组件的问题详见【element ui】问题集锦(el-xxx)专题文章。
一、数字类型校验的问题
代码
<el-dialog v-dialogDrag width="800px" :visible.sync="dialogVisible" @close="reset" >
<el-form :model="deviceBox" :rules="rules" ref="deviceBox" label-width="100px">
<el-form-item label="数量" prop="quantity">
<el-input v-model.number="deviceBox.quantity"></el-input>
<!-- <el-input v-model="deviceBox.quantity"></el-input> -->
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submitForm">确 定</el-button>
</div>
</el-dialog>
rules: {
quantity: [
{type: 'number', message: '数量必须为数字值'}
]
}
reset () {
this.deviceBox = {
'quantity': 1
}
}
注意
数字类型的验证需要在 v-model处加上 .number 的修饰符,这是 Vue 自身提供的用于将绑定值转化为 number 类型的修饰符。
现象
- 当输入’1test’时,校验通过,提交保存强制转化为1;
- 当输入’test1’时,校验不通过,提示数量必须为数字值。
问题
当输入’1test’时,校验通过,提交保存强制转化为1。
但是关闭对话框,再打开时,输入框默认显示的不是1而是’1test’,猜测是el-form有缓存导致。
因为虽然每次关闭对话框执行了reset(),但是给deviceBox.quantity设置的值还是1,和’1test’强制转换成的1一致,估计el-form就没有刷新当前的输入框。
结论
在重置函数reset()中设置deviceBox.quantity为任意数值N,输入’Ntest’时都会出现如上所述问题。
只有改reset()强制重置deviceBox.quantity变量为空即可,因为输入框无法输入’‘会提示’数量必须为数字值’:
reset () {
this.deviceBox = {
'quantity': ''
}
}
二、el-tree 设置默认值
单选树设置默认值
<!-- 单选树 -->
<el-tree ref="tree" :data="treeMenus" :props="defaultProps" accordion @node-click="handleNodeClick" :node-key="nodeId" :filter-node-method="filterNode" highlight-current :expand-on-click-node="true" :default-expanded-keys="[defaultId]">
<span class="span-ellipsis" slot-scope="{ node }">
<span :title="node.label">{{ node.label }}</span>
</span>
</el-tree>
created () {
// 给单选树赋默认值
if (this.setDefultId !== undefined) {
this.defaultId = this.setDefultId
}
},
updated () {
// 给单选树设置默认值
if (this.setDefultId !== undefined) {
this.defaultId = this.setDefultId // 这个用于展开树到高亮的节点
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.defaultId) // 这个才是高亮的关键啊
})
}
},
多选树设置默认值
<!-- 多选树 -->
<el-tree ref="tree" :data="treeMenus" :props="defaultProps" :show-checkbox="true" :node-key="nodeId" :filter-node-method="filterNode" highlight-current :expand-on-click-node="false" :default-checked-keys="checkedId" :check-strictly="isStrict" @check="clickDeal">
<span class="span-ellipsis" slot-scope="{ node }">
<span :title="node.label">{{ node.label }}</span>
</span>
</el-tree>
updated () {
// 给多选树设置默认值
if (this.checkedId !== undefined) {
this.$refs.tree.setCheckedKeys(this.checkedId)
}
},
三、修改element-ui样式
因为官方文档并不详细,像官方文档没有说el-aside的宽度怎么设置。
然后我发现,给el-aside的class里设置宽度不行,貌似会被元素样式覆盖掉,非得设置style="width:210px"。
问题来了:我点击某个按钮,通过jequery或者全局变量控制修改el-aside的宽度。同时当我页面上有定时器不断刷新存在时,修改的宽度会恢复成style="width:210px"。
目前解决的办法只有一个,修改element-ui元素样式,再通过jq修改元素el-aside的宽度时,无论定时器setTimeout怎么刷新也不会影响当前样式修改。
此处注意:
- 1、修改样式时通过全局变量控制,会明显出现卡顿现象,最后还是选择通过jequery的.css或者.animate方法。
- 2、setTimeout比setInterval对内存影响更友好。
- 3、正经说说怎么通过正规渠道修改element-ui样式:官网API文档没有那就只能看源码。 比如修改el-aside的宽度,找到文件\node_modules\element-ui\packages\aside\index啥也没有,引入了Aside from './src/main';
继续查看文件./src/main
<aside class="el-aside" :style="{ width }">
<slot></slot>
</aside>
以上可以看出el-aside可以设置修改宽度通过
props: {
width: {
type: String,
default: '300px'
}
}
属性width默认300px,由此可以按照源码样式修改,注意当前值的类型是String,所以设置如下:
<el-aside :width="'210px'">
210px一定要用单引号''括起来转换成String类型。
四、element标签el-select失效
element标签使用时候千万注意string和number类型的对应一致,不然一直不生效,比如:
<el-select v-model="validTime" clearable placeholder="请选择">
<el-option v-for="item in validTimeData" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
validTimeData = [{"label":"20分钟","value":"20"},{"label":"5分钟","value":"5"}]
当validTime = "20"时,显示正常20分钟,
当validTime = 20时,显示异常,因为找不到20对应的label,所以显示20。
五、火狐下,el-tab展示的echarts提示Dom has no width or height
思考过程:
- 1、一层层给容器添加高宽100%,没用,同时发现.el-tabs__content没法加宽度100%;
- 2、发现.el-tabs加上border: 1px solid green;后就正常了,很怪;
- 3、与此同时发现echarts内层的div确实获取不到高度,但能正常获取宽度;
- 4、给echarts层的div的class中,赋高度和宽度100%不行,600px也不行,只有在style上赋值600px可以,或者在class中赋值600px !important可以。
然后意识到100% !important是可以的,不过可能是真的100%只有这么高,但是一层层100%的高度为什么到此就没了高度呢。
刚刚不是有个.el-tabs__content没法加宽度吗,查看.el-tabs__content层:position: relative!
晕改为absolute就行了,但是插件原来的样式乱掉了得自己慢慢调整。
- fixed
- 生成绝对定位的元素,相对于浏览器窗口进行定位。
- 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。
- static
- 没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
- inherit
- 规定应该从父元素继承 position 属性的值。
- relative
- 生成相对定位的元素,相对于其正常位置进行定位。
- 因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。
- absolute
- 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。
- 元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。
六、element树中的default-expanded-keys一旦加载无法修改的问题
通常使用el-tree如下:
<el-tree ref="tree" :default-expanded-keys="[defaultId]"></el-tree>
但项目里,将其嵌入组件中这么用时:
<el-dialog :visible.sync="deptVisible" append-to-body>
<my-tree>
<el-tree ref="tree" :default-expanded-keys="[defaultId]"></el-tree>
</my-tree>
</el-dialog>
有个问题:
在弹出框中包含el-tree,初始化el-tree时,给默认展开赋值defaultId,弹出框关闭重新弹出即便defaultId改变了,el-tree的默认展开还是没变。
尝试修改:
defaultId改变时父组件调用子组件的设置选中值和当前高亮值的方法,如下
this.$refs.tree.setCheckedKeys([defaultId])
this.$refs.tree.setCurrentKey(defaultId)
发现当弹出框关闭后打开,defaultId变化后,确实选中和高亮变了,但是之前的展开项仍然展开!!
百度发现:
这篇文章说到【tree和tree-store都没有提供收起节点的方法】。。。
于是思考:
遍历是不可能的,但是我可以让el-tree更新或者重新加载啊!
了解到VUE的生命周期:
updated是当data里的数据有变化时触发,而不是父组件传递过来的props,props是一次性的,所以updated无望。
需要注意的是,查看源码可以发现element组件的dialog方法用的v-show,只是隐藏了对话框部分,所以即便关闭了对话框,里面的组件并没有销毁。
那么我可以在dialog隐藏的时候,通过v-if使得tree销毁啊啊!!!
如下设置即可:
<el-dialog :visible.sync="deptVisible" append-to-body>
<my-tree v-if="deptVisible"></my-tree>
</el-dialog>
七、清除浮动很重要
使用el-form布局时有个问题,如果想分两栏布局,左边一列右边一列,最下面还有合起来一个,像这样:
<el-form label-width="80px" size="mini">
<div class="info-left">
<el-form-item label="设备ID:"><el-input v-model="devInfo.info.id"></el-input></el-form-item>
</div>
<div class="info-right">
<el-form-item label="设备类型:"><el-input v-model="devInfo.info.dtype"></el-input></el-form-item>
</div>
<el-form-item label="备注:">
<el-input type="textarea" v-model="devInfo.info.remarks"></el-input>
</el-form-item>
</el-form>
.el-form .info-left {
width: 49%;
float: left;
}
.el-form .info-right {
width: 49%;
float: right;
}
然后发现,除了最下面的备注可以正常输入操作,上面两栏没法正常输入使用。 为什么呢?不知道啊,好奇怪哦。 突然意识到上面左右两栏没有清除浮动啊,清除了一下结果果然好了啊。
<el-form label-width="80px" size="mini">
<div class="info-left">
<el-form-item label="设备ID:"><el-input v-model="devInfo.info.id"></el-input></el-form-item>
</div>
<div class="info-right">
<el-form-item label="设备类型:"><el-input v-model="devInfo.info.dtype"></el-input></el-form-item>
</div>
<div style="clear:both"></div>
<el-form-item label="备注 :">
<el-input type="textarea" v-model="devInfo.info.remarks"></el-input>
</el-form-item>
</el-form>
结论:清除浮动真的很重要!!!
另外:
在使用el-tabs等组件时,火狐下也会出现高度显示异常,但凡DIV高宽异常时,按如下步骤排查:
- 1、确定用百分数异常,查看其外层div是否设置高宽。
- 2、查看是否存在浮动没有清除。
- 3、检查position的设置是否合理。
八、this.$confirm闪退的问题
<a href="#" @click="downloadDoc"><i class="iconfont" ></i></a>
downloadDoc () {
this.$confirm('是否需要下载帮助文档?', '下载', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'info'
})
.then(() => {
this.helpDocDownload()
this.$message({
type: 'success',
message: '下载成功!'
})
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消下载'
})
})
}
初次点击a标签时,弹出框会闪退,再次点击正常。
因为href="#"会定位到页面顶部,即出现,点击弹出框外部导致弹出框退出关闭的效果。
将标签改为如下即可:
<a href="javascript:void(0)" @click="downloadDoc"><i class="iconfont" ></i></a>
九、$message报错
报错代码:
Vue.prototype.$message.info(res.data.errorMessage)
报错信息:
TypeError: Cannot set property 'type' of undefined
at Function.Message.<computed> [as info] (element-ui.common.js?ccbf:26452)
at eval (index.js?16ca:126) "get请求出错!"
正确代码:
Vue.prototype.$message(
{
type: 'info',
message: res.data.errorMessage
}
)
十、冒号绑定值的问题
在vue中绑定属性值时,比如
<el-dialog :title="dialogTitle"></el-dialog>
1、若title前不加冒号:
<el-dialog title="dialogTitle"></el-dialog>
会被当做html文本处理成字符串,也就是title最终渲染出来是字符串"dialogTitle"
2、若title前加冒号:
<el-dialog :title="dialogTitle"></el-dialog>
会被当做模板处理,在渲染的时候会进行相应的填值处理。
所以
当dialogTitle处为数值、布尔值时,必须要在title前加上冒号,比如:
<el-dialog :title="true"></el-dialog>
<el-dialog :title="101"></el-dialog>
否则会被当成字符串true和字符串101。
十一、el-date-picker切换type错乱
<el-date-picker v-model="value1" :type="dateType" placeholder="选择日期"> </el-date-picker>
当dateType显示类型动态变换(year/month/date/dates/ week/datetime/datetimerange/ daterange/monthrange)时,出现样式错乱。
尝试给样式禁用动画效果:
.el-date-editor {
transition: none !important;
}
没用。
尝试设置setTimeout,设置时长1s+确实可以,但是设置0或者使用nextTick都没用。
结果:赋个:key值即可!!!
<el-date-picker :key="key" v-model="value1" :type="dateType" placeholder="选择日期"> </el-date-picker>
十二、el-date-picker的格式化
<el-date-picker v-model="planTime" type="datetime" placeholder="选择日期时间" value-format="yyyy-MM-dd HH:mm:ss">
需要注意的是value-format中,小时需要是大写的HH才表示24小时制,若写的hh:mm:ss显示的是12小时制。