Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

C V series features:

  1. Focus only on the implementation of functionality. Let you copy and paste can feel at ease to use
  2. Code comments will be detailed, line by line if possible, to clarify the details
  3. Involving third-party libraries and so on do not repeat, the library will be used for you to put a link to facilitate your in-depth understanding

Function demonstration

So without further ado about the code

When using

<! -- integer + event -->
 <MjInput
    v-model="source.num"
    :min="1"
    :max="999999"
    placeholder="Please fill in"
    @blur="source.num=checkMm(source.num, 1, 999999)"
/>
<! -- float + slot + event -->
<MjInput
    v-model="price"
    class="money"
    type="float"
    clearable
    @blur="priceJudge"
    @keyup.enter.native="queryData(1,'search')"
>
    <i slot="prefix" class="unit">RMB</i>
</MjInput>
Copy the code

Packaging components

The parent component

<template> <! $listeners ensure that the packaged components can be written using el-input --><component :is="show_component" v-model="curVal" v-bind="$attrs" v-on="$listeners">
        <! -- There is no slot that cannot use el-input -->
        <template v-for="(index, name) in $slots" v-slot:[name] >
            <slot :name="name"></slot>
        </template>
    </component>
</template>

<script>
import Int from './int' // int Specifies the integer type
import Float from './float' // float Indicates the floating point type

// Component constants are not stored in data and need not be hijacked by vue
const COMPONENTENUM = {
    int: 'Int'.float: 'Float'
}

export default {
    name: 'MjInput'.components: { Int, Float },
    props: {
        value: { // The value passed in by the parent component V-model
            type: [String.Number].default: ' '
        },
        type: { // The component to render, note that it directly hijacks the type attribute passed in and does not pass the default int to the child component
            type: String.default: 'int'}},data() {
        return {
            curVal: ' ' // Current data}},computed: {
        show_component() {
            return COMPONENTENUM[this.type]
        }
    },
    watch: {
        value: {
            handler(val) {
                // can not be used directly because '' is judged to be false! Val,
                // Since the value is passed in, the child component keeps one-way data flow and cannot modify the value directly, so make a deep copy of the variable assigned to data(val ! = =null&& val ! = =undefined) && (this.curVal = JSON.parse(JSON.stringify(val)))
            },
            // Immediately; Verify that the handler function is executed with the current initial value
            immediate: true
        },
        // Listen for changes in the current value to be submitted to the parent component
        curVal(val) {
            // The value of the sugar in the v-model will emit 'input' by default.
            this.$emit('input', val)
        }
    }
}
</script>
Copy the code

Child component ==> floating point class

<template> <! -- Decimal point component --> <! $listeners ensure that the packaged components can be written using el-input --><el-input v-model.trim="curVal" v-bind="$attrs" @input="inputEvent" v-on="$listeners">
        <! -- There is no slot that cannot use el-input -->
        <template v-for="(index, name) in $slots" v-slot:[name] >
            <slot :name="name"></slot>
        </template>
    </el-input>
</template>

<script>

export default {
    name: 'FloatInput'.props: {
        value: { // The value passed in by the parent component V-model
            type: [String.Number].default: ' '}},data() {
        return {
            curVal: ' ' // Current data}},watch: {
         value: {
            handler(val) {
                // can not be used directly because '' is judged to be false! Val,
                // Since the value is passed in, the child component keeps one-way data flow and cannot modify the value directly, so make a deep copy of the variable assigned to data(val ! = =null&& val ! = =undefined) && (this.curVal = JSON.parse(JSON.stringify(val)))
            },
            // Immediately; Verify that the handler function is executed with the current initial value
            immediate: true
        },
        // Listen for changes in the current value to be submitted to the parent component
        curVal(val) {
            // The value of the sugar in the v-model will emit 'input' by default.
            this.$emit('input', val)
        }
    },
    methods: {
        inputEvent(value) {
            if(! value)return
            // Resolve macOS input. Identify as in certain circumstances.
            value = value.replace(/. /g.'. ');
            
            // Replace all non-numeric elements, except numeric and.
            value = value.replace(/[^\d.]/g.' ');
            
            // Ensure that only one occurs. There are not many.
            value = value.replace(/\.{2,}/g.'. ');
            
            // The first digit must be a number.
            value = value.replace(/^\./g.' ');
            
            // Only appear once, not more than twice
            value = value.replace('. '.'$# $').replace(/\./g.' ').replace('$# $'.'. ');
            
            // Only two decimals can be entered
            value = value.replace(/^(\-)*(\d+)\.(\d\d).*$/.'$1 $2. $3');
            
            // Only 0 can be entered at the beginning
            value = value.replace(/^0+\d+? /g.'0');

            this.$nextTick(() = > {
                if (Number.isNaN(value)) value = ' '
                this.curVal = value
            })
        }
    }
}
</script>
Copy the code

Child component ==> integer class

<template> <! $listeners ensure that the packaged components can be written using el-input --><el-input v-model.number.trim="curVal" v-bind="$attrs" v-on="$listeners" @input="inputEvent" >
        <! -- There is no slot that cannot use el-input -->
        <template v-for="(index, name) in $slots" :slot="name">
            <slot :name="name"></slot>
        </template>
    </el-input>
</template>

<script>

export default {
    name: 'IntInput'.props: {
        value: { // The value passed in by the parent component V-model
            type: [String.Number].default: ' '
        },
        isStartZero: { // Whether you can enter multiple zeros at the beginning
            type: Boolean.default: false}},data() {
        return {
            curVal: ' ' // Current data}},watch: {
          value: {
            handler(val) {
                // can not be used directly because '' is judged to be false! Val,
                // Since the value is passed in, the child component keeps one-way data flow and cannot modify the value directly, so make a deep copy of the variable assigned to data(val ! = =null&& val ! = =undefined) && (this.curVal = JSON.parse(JSON.stringify(val)))
            },
            // Immediately; Verify that the handler function is executed with the current initial value
            immediate: true
        },
        // Listen for changes in the current value to be submitted to the parent component
        curVal(val) {
            // The value of the sugar in the v-model will emit 'input' by default.
            this.$emit('input', val)
        }
    },
    methods: {
        inputEvent(value) {
            if(! value)return
            
            // Non-numeric substitution is null
            value = value.replace(/[^\d]/g.' ');
            // Whether the flag of 0 can appear at the beginning is passed
            !this.isStartZero && (value = value.replace(/^0+\d+? /g.'0'))
            
            this.$nextTick(() = > {
                this.curVal = value
            })
        }
    }
}
</script>
Copy the code

conclusion

  1. with<component></component>Wrap it with the same component name and usage
  2. with$attrsand $listenersEnsure that encapsulated components can be written with el-input
  3. watchIn the listeningvalueIn order to ensure that the data can be changed in real time. And when viewing the details can be better echo so also addedimmediate: true
  4. inputEventFunction. this.$nextTickBecause you want to make sure that the current DOM changes before the assignment

Welcome to see more C V series C V big method