Vue2.0 完成数字输入框组件
2018-04-17 本文已影响272人
yancolin
下面是最终效果图,简陋版的。
最终效果图
需求:
- 输入框只能输入数字,初始值为5。点击加减,相应减1; 点击+10,输入框数字相应加10。此输入框最大值为100,最小值为0;
- 输入框聚焦的时候,键盘上下相应加减1。
分为index.html,input-number.js,index.js 三个文件。
index.html 入口页
input-number.js 数字输入框组件
index.js 根实例
代码如下:
index.html
注:
- 给input-number绑定一个v-model实现双向数据,赋初始的最大值为100,最小值为0,步长的值对应一次性加10的按钮。
- :是语法糖,代表v-bind。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input-number v-model="value" :max="100" :min="0" :step="10"></input-number>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="input-number.js"></script>
<script src="index.js"></script>
</body>
</html>
input-number.js
注:
1.props可以对父组件的变量进行校验。
2.组件中要使用data,必须是函数且有返回值。
3.给组件input赋初始值currentValue,通过组件中的data给currentValue赋值。
4.单击事件:v-on:click="方法" @click="方法"(简写)
双击事件:v-on:dblclick="方法" @dblclick="方法"(简写)
return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value);
}
Vue.component('input-number',{
template: ' <div class="input-number">'
// + '<input type="text" :value="currentValue" @change="handleChange" @focus="handleInput">'
+ '<input type="text" :value="currentValue" @change="handleChange" @keydown="handleKeydown">'
+ '<button @click="handleDown" :disabled="currentValue <= min">-</button>'
+ '<button @click="handleUp" :disabled="currentValue >= max">+</button>'
+ '<button @click="handleAdd" :disabled="currentValue + 10 >= max">+10</button>'
+ '</div>',
props: {
max: {
type: Number,
default: Infinity
},
min: {
type: Number,
default: -Infinity
},
value:{
type: Number,
default: 0
},
step:{
type:Number,
default:10
}
},
data:function () {
return {
currentValue: this.value
}
},
watch:{
currentValue: function (val) {
this.$emit('input',val);
this.$emit('on-change',val);
},
value: function (val) {
this.updateValue(val);
}
},
methods:{
handleDown: function () {
if( this.currentValue <= this.min ) return;
this.currentValue -= 1;
},
handleUp: function () {
if( this.currentValue >= this.max ) return;
this.currentValue += 1;
},
updateValue: function (val) {
if( val > this.max ) val = this.max;
if( val < this.min ) val = this.min;
this.currentValue = val;
},
handleChange: function (event) {
var val = event.target.value.trim();
var max = this.max;
var min = this.min;
if(isValueNumber(val)){
val = Number(val);
this.currentValue = val;
if(val > max){
this.currentValue = max;
}else if( val < min ){
this.currentValue = min;
}
}else{
event.target.value = this.currentValue;
}
},
handleKeydown: function (event) {
// 上
if(event.keyCode == 38){
this.currentValue += 1;
if( this.currentValue > this.max ){
this.currentValue = this.max;
}
}
// 下
if(event.keyCode == 40){
if(this.currentValue <= 0) return;
this.currentValue -= 1;
}
},
handleAdd: function () {
this.currentValue += this.step;
if( this.currentValue >= this.max ){
this.currentValue = this.max;
}
}
// handleInput: function () {
// // 这是Input框获取焦点事件
// }
},
mounted: function () {
this.updateValue(this.value);
}
});
index.js
var app = new Vue({
el: '#app',
data:{
value:5
}
});