catalogue
2.:oninput dynamic binding and @ input event processing
1. Bidirectional binding
The implementation of bidirectional binding is implemented by v-model in vue2.x. The main codes in this subclass are as follows:
export default { name: 'IpInput', model: { prop: 'ipAddress', event: 'change' }, props: { ipAddress: { type: String, required: true }, disabled: { type: Boolean, default: false } }, methods: { // When the focus is lost, judge whether the input is completed and pass ip to the parent component submitIp() { this.$nextTick(() => { if (!(this.ip1 === '') && !(this.ip2 === '') && !(this.ip3 === '') && !(this.ip4 === '')) { const ipVal = this.ip1 + '.' + this.ip2 + '.' + this.ip3 + '.' + this.ip4 console.log(ipVal) this.$emit('change', ipVal) } else { return } }) } } }
The calls in the parent class are as follows
<ip-input v-model="tab.server" :disabled="tab.format !=='RTMP Push' && tab.format !=='RTMPS Push'" />
The tab.server value here will be passed to the prop named ipAddress. At the same time, when < IP input > triggers a change event with a new value, the tab.server property will be updated. In the submitIp() method, the this.$emit('change', ipVal) method is called to return the new value to the parent component.
2.:oninput dynamic binding and @ input event processing
1) Using oninput binding, this method will lead to the inconsistency between v-model and value in the case of Chinese input method. The reason is that in the case of Chinese input method, the v-model in vue will automatically return, and the value is variable, but the value bound by v-mode remains unchanged.
oninput="value=value.replace(/[^0-9]/g, '')"
2) Use: oninput dynamic binding. This method must be combined with this. $nexttick (() = > {}) in the watch to correctly update the DOM data, because this.$refs.ip1.focus() is used in the watch to operate the dom. The DOM in vue is updated asynchronously. This. $nexttick (() = > {}) is a micro task, which is similar to promise in my opinion. Promise in ES6 is very important, such as this.$store.dispatch(), axios and others are promise, which is mainly used to make asynchronous tasks execute sequentially through. then(). The asynchronous execution of js is to execute synchronous tasks in the execution stack first, and then fetch data from the task queue after the execution stack is empty. I just mention it in general here. I've only studied the front end for a month, and I'm still learning. I only know a little about it.
:oninput="ip1=ip1.replace(/[^0-9]/g, '')"
3) Use @ input event handling
@input="ip1=ip1.replace(/[^0-9]/g, '')"
The main differences between @ input and: oninput are as follows:
: oninput will execute the watch method when inputting Chinese and English. This means that inputting Chinese or English will listen to the change of ip in the input box, and it will be executed twice after my test.
@In the input case, inputting Chinese or English will not execute the watch method, indicating that inputting Chinese or English in this case will directly change the value.
I guess the reason is: oninput binds values through v-bind, while @ binds events through v-on. It will directly execute the statements inside. I hope you can give guidance in the comment area.
3. Main functions
1) Cannot input non numbers. In case of input method, it will be processed after the input is completed
2) After entering three digits, the focus will jump to the right automatically
3) Press "↑" to move the focus to the left and "↓" to move the focus to the right (this is not solved temporarily. Press the left and right keys to jump the cursor inside and between the input boxes at the same time. Friends who understand can give guidance in the comment area)
4) Non 0 automatically removes the previous 0, for example: 036 - > 36000 - > 0
5) If the input box is empty, it will be automatically set to 0
4. Custom component code
The custom component code is as follows:
<template> <div :class="disabled ? 'disabled' : ''" class="ip-box"> <el-input ref="ip1" :disabled="disabled" v-model="ip1" maxlength="3" @input="ip1=ip1.replace(/[^\d]/g,'')" @keyup.native="keyupEvent(1,$event)" @blur="syncIp1(),submitIp()"/> <div class="ip-dot" /> <el-input ref="ip2" :disabled="disabled" v-model="ip2" maxlength="3" @input="ip2=ip2.replace(/[^\d]/g,'')" @keyup.native="keyupEvent(2,$event)" @blur="syncIp2(),submitIp()"/> <div class="ip-dot" /> <el-input ref="ip3" :disabled="disabled" v-model="ip3" maxlength="3" @input="ip3=ip3.replace(/[^\d]/g,'')" @keyup.native="keyupEvent(3,$event)" @blur="syncIp3(),submitIp()"/> <div class="ip-dot" /> <el-input ref="ip4" :disabled="disabled" v-model="ip4" maxlength="3" @input="ip4=ip4.replace(/[^\d]/g,'')" @keyup.native="keyupEvent(4,$event)" @blur="syncIp4(),submitIp()"/> </div> </template> <script> export default { name: 'IpInput', model: { prop: 'ipAddress', event: 'change' }, props: { ipAddress: { type: String, required: true }, disabled: { type: Boolean, default: false } }, data() { return { ip1: '', ip2: '', ip3: '', ip4: '' } }, watch: { 'ip1': { handler: function() { this.$nextTick(() => { console.log(this.ip1) if (this.ip1.length === 3) { this.$refs.ip2.focus() } }) } }, 'ip2': { handler: function() { this.$nextTick(() => { if (this.ip2.length === 3) { this.$refs.ip3.focus() } }) } }, 'ip3': { handler: function() { this.$nextTick(() => { if (this.ip3.length === 3) { this.$refs.ip4.focus() } }) } } }, created() { if (this.ipAddress !== '') { // split() splits a string into an array of substrings const ipList = this.ipAddress.split('.') this.ip1 = ipList[0] this.ip2 = ipList[1] this.ip3 = ipList[2] this.ip4 = ipList[3] } }, methods: { // Three digit automatic jump. If the ip exceeds 255, set it to 255 and remove the previous 0 syncIp1() { if (this.ip1 === '') { this.ip1 = '0' } else if (parseInt(this.ip1) > 255) { this.ip1 = '255' this.$message({ message: 'This is not a valid value, please specify a 0-255 Values between', type: 'error' }) } else if (this.ip1 === '0' || this.ip1 === '00' || this.ip1 === '000') { this.ip1 = '0' } else { this.ip1 = this.ip1.replace(/\b(0+)/g, '') } }, syncIp2() { if (this.ip2 === '') { this.ip2 = '0' } else if (parseInt(this.ip2) > 255) { this.ip2 = '255' this.$message({ message: 'This is not a valid value, please specify a 0-255 Values between', type: 'error' }) } else if (this.ip2 === '0' || this.ip2 === '00' || this.ip2 === '000') { this.ip2 = '0' } else { this.ip2 = this.ip2.replace(/\b(0+)/g, '') } }, syncIp3() { if (this.ip3 === '') { this.ip3 = '0' } else if (parseInt(this.ip3) > 255) { this.ip3 = '255' this.$message({ message: 'This is not a valid value, please specify a 0-255 Values between', type: 'error' }) } else if (this.ip3 === '0' || this.ip3 === '00' || this.ip3 === '000') { this.ip3 = '0' } else { this.ip3 = this.ip3.replace(/\b(0+)/g, '') } }, syncIp4() { if (this.ip4 === '') { this.ip4 = '0' } else if (parseInt(this.ip4) > 255) { this.ip4 = '255' this.$message({ message: 'This is not a valid value, please specify a 0-255 Values between', type: 'error' }) } else if (this.ip4 === '0' || this.ip4 === '00' || this.ip4 === '000') { this.ip4 = '0' } else { this.ip4 = this.ip4.replace(/\b(0+)/g, '') } }, // When the focus is lost, judge whether the input is completed and pass ip to the parent component submitIp() { if (!(this.ip1 === '') && !(this.ip2 === '') && !(this.ip3 === '') && !(this.ip4 === '')) { const ipVal = this.ip1 + '.' + this.ip2 + '.' + this.ip3 + '.' + this.ip4 console.log(ipVal) this.$emit('change', ipVal) } else { return } }, // Press the left and right keys to move the focus left and right keyupEvent(index, e) { this.$nextTick(() => { // Press the '↑' key to shift the focus to the left if (e.keyCode === 38) { if (index === 2) { this.$refs.ip1.focus() } else if (index === 3) { this.$refs.ip2.focus() } else if (index === 4) { this.$refs.ip3.focus() } } else if (e.keyCode === 40) { // Press the '↓' key to shift the focus to the right if (index === 1) { this.$refs.ip2.focus() } else if (index === 2) { this.$refs.ip3.focus() } else if (index === 3) { this.$refs.ip4.focus() } } }) } } } </script> <style lang='scss' scoped> .ip-box { width: 202px; border:1px solid #dcdfe6; border-radius: 5px; height: 38px; display: flex; align-items: center; justify-content: center; position: relative; >>> .el-input__inner { border: 0 !important; padding: 0; text-align: center; } >>> .el-input { width: 48px; } &.disabled { background-color: #f5f7fa; color: #c0c4cc; cursor: not-allowed; } } .ip-dot { margin-top: 7px; display: inline-block; width: 3px; height: 3px; border-radius: 50%; background-color: #606266; } .disabled { .ip-dot { background-color: #c0c4cc; } } </style>
scss is used. You need to use sass loader to select the appropriate version of the project
npm install sass-loader@Version number --save-dev
To change the style in element UI, you need to use the > > > depth selector or / deep / depth selector
The parent component is invoked as follows:
<ip-input v-model="tab.server" :disabled="tab.format !=='RTMP Push' && tab.format !=='RTMPS Push'" />
The v-model is bound with ip address, String type, disabled, whether to disable input (read-only), and the default is false
Bloggers have only taught themselves about the front-end for one month. There must be something to optimize this code, which can be written more concise. What problems can be commented and discussed
Code subject reference Yidamuyanol Articles