Vue2.0 完成数字输入框组件

2018-04-17  本文已影响272人  yancolin

下面是最终效果图,简陋版的。


最终效果图

需求:

  1. 输入框只能输入数字,初始值为5。点击加减,相应减1; 点击+10,输入框数字相应加10。此输入框最大值为100,最小值为0;
  2. 输入框聚焦的时候,键盘上下相应加减1。

分为index.html,input-number.js,index.js 三个文件。
index.html 入口页
input-number.js 数字输入框组件
index.js 根实例
代码如下:

index.html

注:

  1. 给input-number绑定一个v-model实现双向数据,赋初始的最大值为100,最小值为0,步长的值对应一次性加10的按钮。
  2. :是语法糖,代表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
    }
});
上一篇下一篇

猜你喜欢

热点阅读