Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
C V series features:
- Focus only on the implementation of functionality. Let you copy and paste can feel at ease to use
- Code comments will be detailed, line by line if possible, to clarify the details
- 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
- with
<component></component>
Wrap it with the same component name and usage - with
$attrs
and$listeners
Ensure that encapsulated components can be written with el-input watch
In the listeningvalue
In 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
inputEvent
Function.this.$nextTick
Because you want to make sure that the current DOM changes before the assignment
Welcome to see more C V series C V big method