在一个项目开发时,经常用到input组件或者textarea组件,当前项目使用的时antdv@1.7.8。提交测试时,测试人员反馈AInput和ATextarea组件没有限制字符长度导致保存时数据库插入报错,因此需要在前端需要限制字符长度。由于项目已经开发过半,因此想通过使用设置默认值方式设置maxLength属性。
确定方案
- 普通input最大长度默认设置为64
- textarea最大长度设置为200
最终实现
再main.js文件中增加代码
import Antd, { Input } from "ant-design-vue";
Input.props.maxLength.default = 64;
然后手动再将每个ATextarea单独增加:max-length="200"
踩坑过程
- 开始想通过修改默认值的方式分别修改AInput、ATextarea两类组件,代码如下:
src\main.js
import Antd, { Input } from "ant-design-vue";
Input.props.maxLength.default = 64;
Input.TextArea.props.maxLength.default = 200;
-
运行结果
结果发现AInput和ATextarea组件的maxlength都变成了200 -
原因查找
\node_modules\ant-design-vue\es\input\TextArea.js
使用函数式组件编写,核心代码如下
import inputProps from './inputProps';
var TextAreaProps = _extends({}, inputProps, {autosize: PropTypes.oneOfType([Object, Boolean]),autoSize: PropTypes.oneOfType([Object, Boolean])
});export default {name: 'ATextarea',inheritAttrs: false,props: _extends({}, TextAreaProps),render: function render() {var props = {props: _extends({}, getOptionProps(this), {prefixCls: prefixCls,inputType: 'text',value: fixControlledValue(stateValue),element: this.renderTextArea(prefixCls),handleReset: this.handleReset}),on: getListeners(this)};return h(ClearableLabeledInput, props);}
}
ATextarea组件的props属性使用的_extends({}, TextAreaProps)
进行浅拷贝
\node_modules\ant-design-vue\es\input\Input.js
也使用函数式组件编写,代码如下:
import inputProps from './inputProps';
export default {name: 'AInput',inheritAttrs: false,props: _extends({}, inputProps),render: function render() {var props = {props: _extends({}, getOptionProps(this), {}),on: getListeners(this)};return h(ClearableLabeledInput, props);}
};
同样AInput组件的props属性也使用的_extends({}, inputProps)
进行浅拷贝
node_modules\ant-design-vue\es\input\inputProps.js
定义了props属性
import PropTypes from '../_util/vue-types';
export default {maxLength: PropTypes.number,
};
结论:PropTypes.number
是引用类型,因此被浅拷贝后实际都是一个地址。无论给AInput还是ATextarea的maxlength赋默认值最终是相互影响的,所以导致上边的问题。
node_modules\ant-design-vue\es\_util\vue-types\index.js
定义vue类型的公共代码
var VuePropTypes = {get number() {return toType('number', {type: Number}).def(currentDefaults.number);},
}
node_modules\ant-design-vue\es\_util\vue-types\utils.js
定义vue类型的公共代码
/*** Adds `isRequired` and `def` modifiers to an object* @param {string} name - Type internal name* @param {object} obj - Object to enhance* @returns {object}*/
export var toType = function toType(name, obj) {Object.defineProperty(obj, '_vueTypes_name', {enumerable: false,writable: false,value: name});withRequired(obj);withDefault(obj);//定义默认值,实际上为obj添加了一个def方法,通过该方法定义默认值if (isFunction(obj.validator)) {obj.validator = obj.validator.bind(obj);}return obj;
};/*** Adds a `def` method to the object returning a new object with passed in argument as `default` property* @param {object} type - Object to enhance*/
export var withDefault = function withDefault(type) {Object.defineProperty(type, 'def', {value: function value(def) {if (def === undefined && this['default'] === undefined) {this['default'] = undefined;return this;}if (!isFunction(def) && !validateType(this, def)) {warn(this._vueTypes_name + ' - invalid default value: "' + def + '"', def);return this;}this['default'] = isArray(def) || isPlainObject(def) ? function () {return def;} : def;return this;},enumerable: false,writable: false});
};