美文网首页
Vue组件库开发—input区间输入组件

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

作者: 一名有马甲线的程序媛 | 来源:发表于2021-05-29 15:36 被阅读0次

    最近闲来无事,接了个组件库开发的活,在这里先记录一下~
    !!! 写作不易,如要转裁,请标明转载出处。
    本文借鉴于element-ui组件库的源码

    1. 项目结构

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

    1.1 新建组件文件

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

    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的文档文件,控制说明文档的样式也可以写在这里~

    <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 为数组格式,数组中第一个元素为区间输入的起始值,数组中的第二个元素为区间输入的结束值。

    <range-input
        type="money"
        placeholder="请输入金额"
        clearable
        v-model="moneyData"
        @input="moneyInput"
        @focus="moneyFocus"
        @blur="moneyBlur"
        @change="moneyChange">
    </range-input>
    
    2.3 组件编码
    <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中的是暴露出去的参数

    <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 样式编码
    <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>
    

    第一次参与组件库的研发与制作,在实现上肯定存在不足的地方,欢迎大家来评论区里留言,感谢大家的批评与指正~
    如果本文对你有所帮助,感谢点一颗小心心,您的支持是我继续创作的动力!

    相关文章

      网友评论

          本文标题:Vue组件库开发—input区间输入组件

          本文链接:https://www.haomeiwen.com/subject/mgnysltx.html