Skip to content
本页目录

Vue组件库开发—input区间输入组件

本文借鉴于element-ui组件库的源码

1. 项目结构

可以去 github 自行下载 element-ui 源码,以下是新建组件的步骤简介,只想看 区间输入框 实现的同鞋可以自行跳过~

1.1 新建组件文件

packages下新建 range-input 文件夹,在其下面新建 index.js

javascript
import RangeInput from './src/range-input.vue';
RangeInput.install = function (Vue) {
  Vue.component(RangeInput.name, RangeInput);
}
export default RangeInput;
1.2 新建组件 vue

packages -> range-input -> src -> range-input.vue
具体的组件逻辑代码都是在这里写的!!!

1.3 引入组件

src -> index.js

1.4 新建md说明文档

examples -> components ->dosc -> range-input.md

1.5 新建文档文件

examples -> components ->views\components-> range-input.vue
在文件中引入步骤4的文档文件,控制说明文档的样式也可以写在这里~

javascript
<template>
  <div class="wrapper">
    <demo></demo>
  </div>
</template>
<script>
import demo from 'examples/components/docs/range-input.md'
export default {
  components: {
    demo
  }
}
</script>
1.6 在菜单中加新组建的路由

examples -> router ->menu.js


2. 区间输入框组件

2.1 区间输入框效果图

区间输入框效果图

2.2 调用实例

由下面的使用组件实例来看,双向绑定了变量 moneyData 为数组格式,数组中第一个元素为区间输入的起始值,数组中的第二个元素为区间输入的结束值。

vue
<range-input
    type="money"
    placeholder="请输入金额"
    clearable
    v-model="moneyData"
    @input="moneyInput"
    @focus="moneyFocus"
    @blur="moneyBlur"
    @change="moneyChange">
</range-input>
2.3 组件编码
vue
<template>
    <div class="range-input"
        :class="{'disabled': disabled}"
        :style="styleName"
        @mouseover="handleMouseover"
        @mouseout="handleMouseout">
        <div class="range-input-box"
            :class="{'active': rangeInputFocus, 'error': svgType == 'error'}">
            <div class="input-box">
                <input type="text"
                    class="range-input"
                    :disabled="disabled"
                    :placeholder="placeholder"
                    v-model="rangeInputs[0]"
                    @input="handleInput"
                    @focus="handleFocus"
                    @blur="handleBlur"
                    @change="handleChange">
            </div>
            <div class="range-input-divider"></div>
            <div class="input-box">
                <input type="text"
                    class="range-input"
                    :disabled="disabled"
                    :placeholder="placeholder"
                    v-model="rangeInputs[1]"
                    @input="handleInput"
                    @focus="handleFocus"
                    @blur="handleBlur"
                    @change="handleChange">
            </div>
            <svg class="svgClass"
                @click="svgType == 'del' && handleClear()"></svg>
        </div>
    </div>
</template>
2.4 方法编码

props中的是暴露出去的参数

vue
<script>
export default {
    name: 'RangeInput',
    props: {
        type: { // 类型 便于表单验证 区间是只能输入钱数 还是整数等
            type: String,
            default:'input'
        },
        width: { // 组件的宽度
            type: String,
            default: '256px'
        },
        placeholder: { // 输入框占位文本
            type: String,
            default: ''
        },
        value: { // 绑定值
            type: Array,
            default: []
        },
        clearable: { // 是否支持清空
            type: Boolean,
            default: false
        },
        disabled: { // 是否禁用
            type: Boolean,
            default: false
        }
    },
    data () {
        return {
            svgClass: '',
            rangeInputFocus: false,
            rangeInputs: [...this.value],
            svgType: this.type,
            validateState: true, // 表单验证结果
            errorMessage: '',
        }
    },
    computed: {
        styleName () {
            return {
                width: this.width
            }
        },
        svgName () {
            return this.svgType == 'money' ? '#svg_sales' : 
                   this.svgType == 'del' ? '#svg_close' : '#svg_draw'
        }
    },
    methods: {
        handleInput () {
            this.$emit('input', [...this.rangeInputs]);
        },
        handleFocus (event) {
            this.rangeInputFocus = true;
            this.$emit('focus', event);
        },
        handleBlur (event) {
            this.rangeInputFocus = false;
            this.$emit('blur', event);
        },
        handleChange () {
            this.$emit('change', [...this.rangeInputs]);
        },
        hanleMouseover () {
            if (!this.validateState) {
                this.svgType = 'error';
            } else {
                this.rangeInputs && this.rangeInputs.length && this.clearable ? this.svgType = 'del' : this.svgType = this.type;
            }
        },
        handleMouseout () {
            if (!this.validateState) {
                this.svgType = 'error';
            } else {
                this.svgType = this.type;
            }
        },
        handleClear () {
            this.rangeInputs = ['', ''];
            this.$emit('input', null);
        }
    }
};
</script>
2.5 样式编码
vue
<style lang="scss" scoped>
%highlight {
    position: absolute;
    bottom: 0;
    left: 0;
    content: '';
    width: 100%;
    height: 1px;
}
.range-input{
    padding: 4px 0;
    .range-input-box{
        position: relative;
        display: flex;
        align-items: center;
        height: 32px;
        line-height: 32px;
        border-radius: 8px;
        background: $c129;
        overflow: hidden;
        &.active:after{
            @extend %hightlight;
            background: $a001;
        }
        &.error:after{
            @extend %hightlight;
            background: $c001;
        }
        .input-box{
            width: calc((100% - 6px - 18px -6px) / 2);
            .range-input{
                width: 100%;
                padding: 0 6px 0 8px;
                @include body1;
                height: 32px;
                line-height: 32px;
                box-sizing: border-box;
                background: transparent;
                color: $c121;
                &::-webkit-input-placeholder{
                    color: $c125;
                }
                &::-moz-placeholder{
                    color: $c125;
                }
            }
        }
        .range-input-divider{
            content: '';
            width: 6px;
            height: 1px;
            background: $c126;
        }
    }
    &:hover{
        .range-input-box{
            background: $c128;
        }
    }
    &.disabled{
        .range-input-box{
            cursor: not-allowed;
            background: $c130;
        }
    }
}
</style>

原文