本文介绍如何在Vue.js中开发一个限制只能输入数字的自定义输入框组件。通过组件封装、监听器控制以及利用eval函数实现与父组件数据的双向绑定,解决单向绑定的局限,并提供扩展字母或中文输入的可能性。
Vue.js数字输入框组件实现概述
在菜鸟教程学习Vue.js后,为了巩固知识并练习实战,尝试实现一个仅允许输入数字的输入框功能。此前曾使用jQuery实现过类似效果,此次改用Vue.js进行开发,并将具体实现过程记录下来。
若仅涉及单个输入框,实现难度较低。只需将输入框内容与数据绑定,并对该数据添加监听器即可。具体代码实现如下:
基础单向绑定实现
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="div1">
<input v-model="content">
</div>
<script>
var mydata = new Vue({
el: '#div1',
data: {
content: ''
},
watch: {
content: function(val){
this.content = val.replace(/\D/g, '')
}
}
})
</script>
</body>
</html>
然而,若页面或系统中存在大量此类输入框,上述方式并非最佳实践。为每个数据单独添加监听器会导致后续需求变更(如允许输入数字和字母)时修改成本极高。此外,该方式缺乏代码可移植性,迁移至其他系统时需重新编写。因此,需要编写通用方法以满足需求,此时应利用Vue的组件功能。新建一个名为num.js的文件,其内部代码如下:
通用组件封装与单向数据同步
Vue.component('number', {
template: '<input type="text" v-model="con">',
data: function(){
return {
con: ''
}
},
watch: {
con: function(val){
this.con = val.replace(/\D/g, '');
}
}
})
上述代码定义了一个名为number的组件,内部包含一个输入框,其内容与数据con绑定,并通过监听器确保con的值仅包含数字。在HTML页面中引入num.js后,通过添加<number></number>标签即可在浏览器中渲染出该输入框。虽然页面放置输入框旨在供用户输入内容供程序使用,但获取输入内容的方式需符合Vue的设计理念。若使用jQuery,通常通过DOM操作获取值,但这与Vue数据与DOM分离的理念相悖。因此,应使输入框与特定数据绑定,以便程序直接获取数据。

假设页面中有三个输入框,需分别将其内容绑定至val1、val2、val3。初始思路是在number标签上定义一个方法,当组件内con的值发生变化时触发该方法并传递con的值,该方法再调用父级mydata中的方法,经过两次传递将值赋给对应变量。这种逻辑较为繁琐,且使用者需在mydata中手动定义赋值方法,体验不佳。改进方案是:既然输入框需绑定数据,则应明确指定绑定的对象及属性名。例如,在number标签上指定对象为mydata,属性名为val1、val2或val3。传递对象时传入的是字符串'mydata'而非对象本身,如何在组件内使用该对象?此时需借助JavaScript中强大的eval函数。eval接收字符串参数,将其作为JavaScript代码解析并执行。具体代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vue</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
<script src="num.js"></script>
</head>
<body>
<div id="div1">
<number objname="mydata" keys="val1"></number>
<number objname="mydata" keys="val2"></number>
<number objname="mydata" keys="val3"></number>
<p>第一个输入框的内容是: {{val1}}</p>
<p>第二个输入框的内容是: {{val2}}</p>
<p>第三个输入框的内容是: {{val3}}</p>
</div>
<script>
var mydata = new Vue({
el: '#div1',
data: {
val1: '',
val2: '',
val3: ''
}
})
</script>
</body>
</html>
num.js组件代码实现如下:
Vue.component('number', {
props: ['objname', 'keys'],
template: '<input type="text" v-model="con">',
data: function(){
return {
con: ''
}
},
watch: {
con: function(val){
this.con = val.replace(/\D/g, '');
eval(this.objname+'[this.keys]=this.con');
}
},
})
运行效果如图所示:

此时,输入框已限制仅能输入数字,并与数据实现了绑定。但需注意,这仅是单向绑定:输入框内容改变时,外部数据随之更新;然而,若外部数据发生变化,输入框内容并不会同步更新。为了验证这一点,可在页面下方添加三个普通输入框,分别绑定val1、val2、val3。

实际操作页面时发现,上方自定义输入框内容的改变会影响下方普通输入框的显示,但反之则不成立,即下方输入框内容的改变不会影响上方自定义输入框。

为实现反向绑定,需在组件内部为外部数据添加监听器。尽管拥有对象和属性名可以添加监听器,但需明确外部属性应绑定至哪个组件内的输入框。因此,需在number标签上增加一个ref属性,该属性是Vue定义的用于查找子组件的标识。最终代码调整为:
实现双向数据绑定
<div id="div1">
<number ref="val1" objname="mydata" keys="val1"></number>
<number ref="val2" objname="mydata" keys="val2"></number>
<number ref="val3" objname="mydata" keys="val3"></number>
<p>第一个输入框的内容是: {{val1}}</p>
<p>第二个输入框的内容是: {{val2}}</p>
<p>第三个输入框的内容是: {{val3}}</p>
<input v-model="val1">
<input v-model="val2">
<input v-model="val3">
</div>
num.js组件内部实现如下:
Vue.component('number', {
props: ['objname', 'keys'],
template: '<input type="text" v-model="con">',
data: function(){
return {
con: ''
}
},
mounted: function(){
var self = this;
window.addEventListener('load', function(){
eval(self.objname+'.$watch(\''+self.keys+'\',function(val){this.$refs.'+self.keys+'.con=val})');
})
},
watch: {
con: function(val){
this.con = val.replace(/\D/g, '');
eval(this.objname+'[this.keys]=this.con');
}
},
})
组件优化与扩展建议
至此,数据实现了双向绑定。需注意,mounted生命周期中的addEventListener方法存在兼容性问题,IE8及以下版本不支持该方法,本文未做兼容处理。此外,代码仍有优化空间:观察number标签可知,ref和keys属性功能相似,是否可合并?经实验发现,在组件内部直接获取ref的值存在困难,目前尚未找到有效获取方式,技术深度有待加强。另外,objname参数是否必须传递?若不传递,可默认使用组件的父对象,此功能可实现。最后,组件还可进一步扩展,例如添加mytype属性:若不传值,默认仅允许输入数字;若设置为'word',则允许输入字母和数字;若设置为'chinese',则仅允许输入中文字符等。
更多教程请点击《Vue.js前端组件学习教程》,欢迎大家学习阅读。
关于vue.js组件的教程,请大家点击专题vue.js组件学习教程进行学习。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。