1.背景
最近在使用vuejs对一个angular老系统进行重构,为了方便,使用了element ui作为ui库。开发中遇到一个冷门需求,需要对输入控件的值进行千分位显示,同时保持双向绑定。如输入1000000,需在控件中显示1000,000,而实例data绑定的值为1000000。
2.分析需求
对比老框架angular1,通过设置一个directive全局自定义命令逻辑,实现简单的数据显示 => 数据处理的千分位功能。 对于vue来说,如果使用dom input,可以以相同方式设置directive实现同样功能.但是为了保持UI的一致性,需要对element ui控件进行改造。具体实现是构造自定义组件包裹默认的element ui input组件,自定义组件内部实现普通数字与千分位的转换,外部实现数字与data的双向绑定。
3.涉及冷门知识点
- vue .sync 修饰符,实现props的双向绑定。
- v-bind="someObject" 将一个对象的所有 property 都作为 prop 传入,可以用于传递element input组件相关设置.
post: {
id: 1,
title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
等价与
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
- 正则表达方法replace中,约定了一个特殊标记符”$”:
- $i(i取值范围1~99):表示从左到右正则子表达式所匹配的文本
- $&:表示与正则表达式匹配的全部文本
- $
(:1旁边的那个键):表示匹配字符串的左边文本- $'(':单引号):表示匹配字符串的右边文本
- ?:表示$转移
4.具体实现
1)设置名为CustomInput的组件并引入(注意sync修饰符)
<CustomInput :value.sync="test" :options="optionObject" />
2)编写CustomInput逻辑
<template>
<el-input v-model="defaultValue" @input="changeInput" v-bind="options" />
</template>
<script>
export default {
name: 'CustomInput',
props: {
value: String,
options: Object,
},
data() {
return {
defaultValue: '0',
};
},
mounted() {
this.defaultValue = this.transferToDecimal(this.value);
},
methods: {
transferToDecimal(num) {
if (!num) return;
let [sInt, sFloat] = num.split('.');
// 注意 “$&,”的应用
sInt = sInt.replace(/\d(?=(\d{3})+$)/g, '$&,');
// 区分整数与浮点小数
return sFloat ? `${sInt}.${sFloat}` : `${sInt}`;
},
changeInput(value) {
// 此处允许用户输入点 “.”, 同时如果再次输入点将会被截掉
if (value.charAt(value.length - 1) == '.') {
if (value.charAt(value.length - 2) == '.') {
this.defaultValue = value.substr(0, value.length - 1);
}
return;
}
// 此处防止用户输入特殊字符,具体查看下面正则
value = this.cleanInput(value);
this.defaultValue = this.transferToDecimal(value);
// 此处激活.sync默认行为实现props的双向绑定, 注意'update'
this.$emit('update:value', value);
},
cleanInput(value) {
// 正则表达式只匹配 首位负数, 数字, 以及第一个“.”号(如有多个只匹配一个),提取为数值默认顺序连接,然后通过转换函数转换为千分位
return value.match(/(^-\d+|\d+|\.{1})/g, '').join('');
},
},
};
</script>
3)上述逻辑的思考
-
为什么不直接控制用户最后一个字符的输入,而使用复杂的额外函数cleanInput进行数据修正。 这里考虑到一种情况是用户可能使用复制粘贴功能输入数据。
-
input类型如果设置为number,无法实现千分位的显示,所以有关数据类型的检验需要额外逻辑进行验证,可以在使用这个组件的页面进行实现,或者cleanInput里面添加额外逻辑。
5.后记
一直想写一点儿技术方面的文章,却没有好的切入点。这次借实际开发的一个需求做一个分享,也是我来掘金的第一篇文章,欢迎大家提出意见。