背景
项目是基于antd,需求表单中文本域要求显示当前输入文案字数以及最大限制字数。
实现难点
- 表单校验总是不触发
antd中form-model的校验规则很奇怪,form-item标签下面添加一层标签,校验规则就不触发了,如下多加一层div:
<a-form-model ref="basicInfo" class="basic-info" :model="prodBasicInfo" :rules="rules" layout="inline">
<a-form-model-item label="商品副标题" prop="slogan">
<div>
<a-input v-model="prodBasicInfo.slogan" style="width: 700px" placeholder="最多50个字" :maxLength="50" />
</div>
</a-form-model-item>
...
<a-form-model>
rules: {
slogan: [
{ required: true, message: "商品副标题不能为空", trigger: "blur" },
{ max: 20, message: "名称最多20个字", trigger: "blur" },
],
}
上续情况表单失去焦点事件就校验不触发,那封装组件自然会外套一个标签,本文需要封装的组件dom结构会如下:
<div class="textarea">
<a-input
v-model="textValue"
type="textarea"
class="text-area"
:maxLength="maxLength"
:autoSize="autoSize"
:placeholder="placeholder"
@input="onInput"
@blur="handleBlur"
/>
<span class="fontNum-prompt">{{ value.length }}/{{ maxLength }}</span>
</div>
自然也是校验规则 不触发
解决办法
绑定a-input的失焦事件,将当前表单中的值 抛出去;就可以校验 ----不懂为什么,但确实可以做到;
总体实现代码如下:
<!-- 二次封装 ant 文本框,添加【已输长度/最多长度】显示 -->
<template>
<div class="textarea-plus">
<a-input
v-model="textValue"
type="textarea"
class="text-area"
:maxLength="maxLength"
:autoSize="autoSize"
:placeholder="placeholder"
@input="onInput"
@blur="handleBlur"
/>
<span class="fontNum-prompt">{{ value.length }}/{{ maxLength }}</span>
</div>
</template>
<script>
export default {
name: "AntTextarea",
props: {
value: {
type: [String, Number],
default: null,
},
placeholder: {
type: String,
default: "",
},
maxLength: {
type: Number,
default: null,
},
autoSize: {
type: Object,
default() {
return {
minRows: 2,
};
},
},
},
data() {
return {
textValue: this.value,
};
},
methods: {
handleBlur(e) {
// this.$emit("update:value", e.target.value);
this.$emit("blur", e.target.value);
},
onInput(e) {
this.$emit("update:value", e.target.value);
// this.$emit("input", e.target.value);
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="less" scoped>
.textarea-plus {
position: relative;
.text-area {
padding-bottom: 30px;
}
.fontNum-prompt {
position: absolute;
bottom: 10px;
right: 20px;
line-height: 20px;
color: rgba(0, 0, 0, 0.3);
}
}
</style>