vue模拟input[type=‘number’] 组件功能。
父组件传入最大值,最小值,step
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<style>
[v-cloak]{
display: none;
}
.inputBox{
position: absolute;
}
.inputBox button{
width: 30px;
}
.inputBox input{
padding-left:10px;
width:100px;
}
</style>
</head>
<!--
1.传入值类型判断
2.初始化值范围判断
3.按钮判断(min,max)
4.输入值判断(类型,大小)
-->
<body>
<div id="app">
<input-box v-model="value" :step="step" :min="min" :max="max"></input-box>
</div>
<!-- <div id="app">-->
<!-- // 组件,由父组件传入max,min,及绑定的v-model-->
<!--<!– <num-con v-model="value" :max="10" :min="0"></num-con>–>-->
<!-- </div>-->
<script>
// 第一版
// 判断是否存在数字可以匹配
// function isValueNurnber (value) {
// return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value);
// }
// var numCon={
// // 模板中有一个input,绑定change事件
// // 两个button绑定up和down事件,设置disabled条件。
// template:'<div><input type="text" :value="count" @change="handlechange"><button @click="handledown" :disabled="count<=min">-</button>' +
// '<button @click="handleup" :disabled="count>=max">+</button></div>',
// data:function () {
// // 存储初始化时父组件传入的值
// return {
// // 子组件接收的父组件的值
// // 浅拷贝
// count:this.value
// }
// },
// mounted(){
// // 挂载时判断传入值范围。修改数字
// this.updateVal(this.value);
// },
// props:{
// // 外面传进来的值 max、min、value
// max:{
// type:Number,
// default:Infinity
// },
// min:{
// type:Number,
// default: Infinity
// },
// value:{
// type:Number,
// default:0,
// }
// },
// methods:{
// // 判断范围。
// handledown(){
// if(this.count<=this.min) return;
// this.count--;
// },
// // 判断范围
// handleup(){
// if(this.count>=this.max) return;
// this.count++;
// },
// // 输入事件
// handlechange(event){
// // 获取输入的值,去除空格
// var val = event.target.value.trim();
// var max = this.max;
// var min = this.min;
// if(isValueNurnber(val)){
// val = Number(val);
// this.count=val;
// if(val>max){
// this.count = max;
// }
// else if(val<min){
// this.count = min;
// }
// }else{
// event.target.value=this.count;
// }
// },
// updateVal(val){
// val = val>this.max?this.max:val;
// val = val<this.min?this.min:val;
// this.count=val;
// },
//
// },
// watch:{
// // 监听父组件数据是否改变,子组件跟着改变。
// value:function(newVal){
// this.updateVal(newVal);
// },
// count:function(val){
// // count改变则告知父组件
// // 通过v-model绑定了
// this.$emit('input',val);
// // this.$emit('on-change',val)
// }
// }
//
// };
// var app = new Vue({
// el:'#app',
// components:{
// numCon,
// },
// data:{
// value:5,
// },
// methods:{
// check(value){
// console.log('输出'+(value===this.value))
// }
// }
// })
// 第二版,增加两个小功能。
function isNumVal(val){
return /(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/.test(val);
}
var inputBox={
template:'<div class="inputBox"><button :disabled="num<=min" @click="reduce">-</button><input type="text" @keydown="down" @keyup.40="reduce" @keyup.38="add" :value="num" @change="changNum"><button :disabled="num>=max" @click="add">+</button></div>',
props:{
value:{
type:Number,
default:0,
},
min:{
type:Number,
default: -Infinity,
},
max:{
type:Number,
default:Infinity
},
step:{
type:Number,
default:1,
}
},
data:function(){
return {
num : this.value,
// 初始化时将父组件的值传给子组件
// 在子组件操作num
count:this.step
}
},
mounted() {
this.updateNum(this.value);
},
methods:{
add(){
if(this.num+this.count >this.max) return;
this.num+=this.count;
},
reduce(){
if(this.num-this.count <this.min) return;
this.num-=this.count;
},
down(event){
event.preventDefault();
},
changNum(event){
var val = event.target.value;
// 手动输入文本,通过元素获取值
if(isNumVal(event.target.value)){
val = Number(val);
if(val < this.min){
val = this.min;
}
if(val >this.max){
val = this.max;
}
this.num = val;
}else{
// 不是数组,不改变
event.target.value = this.num;
}
},
updateNum(val){
// 对val进行修改。
if(val<this.min){
val = this.min;
}
if(val>this.max){
val=this.max;
}
this.num = val;
}
},
watch:{
// 监视父组件value的改变
value:function (newVal,oldVal) {
// 判断范围
if(newVal<this.min){
newVal = this.min;
}
if(newVal>this.max){
newVal = this.max;
}
this.num = newVal;
},
num:function (newVal) {
// 通过v-model,子元素触发input,会将父元素传入的值修改为相同的值。
this.$emit('input',newVal);
},
step:function (newVal) {
this.count=newVal;
}
},
}
var app = new Vue({
el:'#app',
data:{
value:5,
min:0,
max:10,
step:2,
},
components:{
inputBox,
}
})
</script>
</body>