uni-easyinput连续输入出现闪动解决

2023-10-17 00:30

本文主要是介绍uni-easyinput连续输入出现闪动解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原因分析:

是因为uni-easyinput源码中,在输入触发事件中一直去同步modelValue,而modelValue其实就是双向绑定的值(有一定延迟),当连续输入时,会导致input和modelValue不一致,就会出现光标闪动(其实就是文本框的值变成了上一次输入的值)

解决方案:

方案一:

1. 按照如下图,去注释onInput方法里面的代码,在_Blur加上代码

	/*** 输入时触发* @param {Object} event*/onInput(event) {let value = event.detail.value;// 判断是否去除空格if (this.trim) {if (typeof this.trim === "boolean" && this.trim) {value = this.trimStr(value);}if (typeof this.trim === "string") {value = this.trimStr(value, this.trim);}}if (this.errMsg) this.errMsg = "";this.val = value;// TODO 兼容 vue2this.$emit("input", value);// TODO 兼容 vue3  uni-easyinput的bug修复光标闪动,将modelvalue的值放在失去光标的时候更新,不实时更新// this.$emit("update:modelValue", value);},

_Blur(event) {let value = event.detail.value;//uni-easyinput的bug修复光标闪动,将modelvalue的值放在失去光标的时候更新this.$emit("update:modelValue", this.val);this.focusShow = false;this.$emit("blur", event);// 根据类型返回值,在event中获取的值理论上讲都是stringthis.$emit("change", this.val);// 失去焦点时参与表单校验if (this.form && this.formItem) {const { validateTrigger } = this.form;if (validateTrigger === "blur") {this.formItem.onFieldChange();}}},

uni-easyinput.vue组件源码如下:请注意区分组件版本,不要直接覆盖

<template><viewclass="uni-easyinput":class="{ 'uni-easyinput-error': msg }":style="boxStyle"><viewclass="uni-easyinput__content":class="inputContentClass":style="inputContentStyle"><slot name="prefixIcon"><uni-iconsv-if="prefixIcon"class="content-clear-icon":type="prefixIcon"color="#c0c4cc"@click="onClickIcon('prefix')"size="22"></uni-icons></slot><textareav-if="type === 'textarea'"class="uni-easyinput__content-textarea":class="{ 'input-padding': inputBorder }":name="name":value="val":placeholder="placeholder":placeholderStyle="placeholderStyle":disabled="disabled"placeholder-class="uni-easyinput__placeholder-class":maxlength="inputMaxlength":focus="focused":autoHeight="autoHeight"@input="onInput"@blur="_Blur"@focus="_Focus"@confirm="onConfirm"></textarea><inputv-else:type="type === 'password' ? 'text' : type"class="uni-easyinput__content-input":style="inputStyle":name="name":value="val":password="!showPassword && type === 'password'":placeholder="placeholder":placeholderStyle="placeholderStyle"placeholder-class="uni-easyinput__placeholder-class":disabled="disabled":maxlength="inputMaxlength":focus="focused":confirmType="confirmType"@focus="_Focus"@blur="_Blur"@input="onInput"@confirm="onConfirm"/><template v-if="type === 'password' && passwordIcon"><!-- 开启密码时显示小眼睛 --><uni-iconsv-if="isVal"class="content-clear-icon":class="{ 'is-textarea-icon': type === 'textarea' }":type="showPassword ? 'eye-slash-filled' : 'eye-filled'":size="22":color="focusShow ? primaryColor : '#c0c4cc'"@click="onEyes"></uni-icons></template><template v-else-if="suffixIcon || $slots.suffixIcon"><slot name="suffixIcon"><uni-iconsv-if="suffixIcon"class="content-clear-icon":type="suffixIcon"color="#c0c4cc"@click="onClickIcon('suffix')"size="22"></uni-icons></slot></template><template v-else><uni-iconsv-if="clearable && isVal && !disabled && type !== 'textarea'"class="content-clear-icon":class="{ 'is-textarea-icon': type === 'textarea' }"type="clear":size="clearSize":color="msg ? '#dd524d' : focusShow ? primaryColor : '#c0c4cc'"@click="onClear"></uni-icons></template><slot name="right"></slot></view></view>
</template><script>
/*** Easyinput 输入框* @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。* @tutorial https://ext.dcloud.net.cn/plugin?id=3455* @property {String}	value	输入内容* @property {String }	type	输入框的类型(默认text) password/text/textarea/..* 	@value text			文本输入键盘* 	@value textarea	多行文本输入键盘* 	@value password	密码输入键盘* 	@value number		数字输入键盘,注意iOS上app-vue弹出的数字键盘并非9宫格方式* 	@value idcard		身份证输入键盘,信、支付宝、百度、QQ小程序* 	@value digit		带小数点的数字键盘	,App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持* @property {Boolean}	clearable	是否显示右侧清空内容的图标控件,点击可清空输入框内容(默认true)* @property {Boolean}	autoHeight	是否自动增高输入区域,type为textarea时有效(默认true)* @property {String }	placeholder	输入框的提示文字* @property {String }	placeholderStyle	placeholder的样式(内联样式,字符串),如"color: #ddd"* @property {Boolean}	focus	是否自动获得焦点(默认false)* @property {Boolean}	disabled	是否禁用(默认false)* @property {Number }	maxlength	最大输入长度,设置为 -1 的时候不限制最大长度(默认140)* @property {String }	confirmType	设置键盘右下角按钮的文字,仅在type="text"时生效(默认done)* @property {Number }	clearSize	清除图标的大小,单位px(默认15)* @property {String}	prefixIcon	输入框头部图标* @property {String}	suffixIcon	输入框尾部图标* @property {String}	primaryColor	设置主题色(默认#2979ff)* @property {Boolean}	trim	是否自动去除两端的空格* @value both	去除两端空格* @value left	去除左侧空格* @value right	去除右侧空格* @value start	去除左侧空格* @value end		去除右侧空格* @value all		去除全部空格* @value none	不去除空格* @property {Boolean}	inputBorder	是否显示input输入框的边框(默认true)* @property {Boolean}	passwordIcon	type=password时是否显示小眼睛图标* @property {Object}	styles	自定义颜色* @event {Function}	input	输入框内容发生变化时触发* @event {Function}	focus	输入框获得焦点时触发* @event {Function}	blur	输入框失去焦点时触发* @event {Function}	confirm	点击完成按钮时触发* @event {Function}	iconClick	点击图标时触发* @slot prefixIcon 输入框头部插槽* @slot suffixIcon 输入框尾部插槽* @example <uni-easyinput v-model="mobile"></uni-easyinput>*/
function obj2strClass(obj) {let classess = "";for (let key in obj) {const val = obj[key];if (val) {classess += `${key} `;}}return classess;
}function obj2strStyle(obj) {let style = "";for (let key in obj) {const val = obj[key];style += `${key}:${val};`;}return style;
}
export default {name: "uni-easyinput",emits: ["click","iconClick","update:modelValue","input","focus","blur","confirm","clear","eyes","change",],model: {prop: "modelValue",event: "update:modelValue",},options: {virtualHost: true,},inject: {form: {from: "uniForm",default: null,},formItem: {from: "uniFormItem",default: null,},},props: {name: String,value: [Number, String],modelValue: [Number, String],type: {type: String,default: "text",},clearable: {type: Boolean,default: true,},autoHeight: {type: Boolean,default: false,},placeholder: {type: String,default: " ",},placeholderStyle: String,focus: {type: Boolean,default: false,},disabled: {type: Boolean,default: false,},maxlength: {type: [Number, String],default: 140,},confirmType: {type: String,default: "done",},clearSize: {type: [Number, String],default: 24,},inputBorder: {type: Boolean,default: true,},prefixIcon: {type: String,default: "",},suffixIcon: {type: String,default: "",},trim: {type: [Boolean, String],default: true,},passwordIcon: {type: Boolean,default: true,},primaryColor: {type: String,default: "#2979ff",},styles: {type: Object,default() {return {color: "#333",disableColor: "#F7F6F6",borderColor: "#e5e5e5",};},},errorMessage: {type: [String, Boolean],default: "",},},data() {return {focused: false,val: "",showMsg: "",border: false,isFirstBorder: false,showClearIcon: false,showPassword: false,focusShow: false,localMsg: "",};},computed: {// 输入框内是否有值isVal() {const val = this.val;// fixed by mehaotian 处理值为0的情况,字符串0不在处理范围if (val || val === 0) {return true;}return false;},msg() {// console.log('computed', this.form, this.formItem);// if (this.form) {// 	return this.errorMessage || this.formItem.errMsg;// }// TODO 处理头条 formItem 中 errMsg 不更新的问题return this.localMsg || this.errorMessage;},// 因为uniapp的input组件的maxlength组件必须要数值,这里转为数值,用户可以传入字符串数值inputMaxlength() {return Number(this.maxlength);},// 处理外层样式的styleboxStyle() {return `color:${this.inputBorder && this.msg ? "#e43d33" : this.styles.color};`;},// input 内容的类和样式处理inputContentClass() {return obj2strClass({"is-input-border": this.inputBorder,"is-input-error-border": this.inputBorder && this.msg,"is-textarea": this.type === "textarea","is-disabled": this.disabled,});},inputContentStyle() {const focusColor = this.focusShow? this.primaryColor: this.styles.borderColor;const borderColor = this.inputBorder && this.msg ? "#dd524d" : focusColor;return obj2strStyle({"border-color": borderColor || "#e5e5e5","background-color": this.disabled? this.styles.disableColor: this.styles.backgroundColor,});},// input右侧样式inputStyle() {const paddingRight =this.type === "password" || this.clearable || this.prefixIcon? "": "10px";return obj2strStyle({"padding-right": paddingRight,"padding-left": this.prefixIcon ? "" : "10px",});},},watch: {value(newVal) {this.val = newVal;},modelValue(newVal) {this.val = newVal;},focus(newVal) {this.$nextTick(() => {this.focused = this.focus;this.focusShow = this.focus;});},},created() {this.init();// TODO 处理头条vue3 computed 不监听 inject 更改的问题(formItem.errMsg)if (this.form && this.formItem) {this.$watch("formItem.errMsg", (newVal) => {this.localMsg = newVal;});}},mounted() {this.$nextTick(() => {this.focused = this.focus;this.focusShow = this.focus;});},methods: {/*** 初始化变量值*/init() {if (this.value || this.value === 0) {this.val = this.value;} else if (this.modelValue || this.modelValue === 0) {this.val = this.modelValue;} else {this.val = null;}},/*** 点击图标时触发* @param {Object} type*/onClickIcon(type) {this.$emit("iconClick", type);},/*** 显示隐藏内容,密码框时生效*/onEyes() {this.showPassword = !this.showPassword;this.$emit("eyes", this.showPassword);},/*** 输入时触发* @param {Object} event*/onInput(event) {let value = event.detail.value;// 判断是否去除空格if (this.trim) {if (typeof this.trim === "boolean" && this.trim) {value = this.trimStr(value);}if (typeof this.trim === "string") {value = this.trimStr(value, this.trim);}}if (this.errMsg) this.errMsg = "";this.val = value;// TODO 兼容 vue2this.$emit("input", value);// TODO 兼容 vue3  uni-easyinput的bug修复光标闪动,将modelvalue的值放在失去光标的时候更新,不实时更新// this.$emit("update:modelValue", value);},/*** 外部调用方法* 获取焦点时触发* @param {Object} event*/onFocus() {this.$nextTick(() => {this.focused = true;});this.$emit("focus", null);},_Focus(event) {this.focusShow = true;this.$emit("focus", event);},/*** 外部调用方法* 失去焦点时触发* @param {Object} event*/onBlur() {this.focused = false;this.$emit("focus", null);},_Blur(event) {let value = event.detail.value;//uni-easyinput的bug修复光标闪动,将modelvalue的值放在失去光标的时候更新this.$emit("update:modelValue", this.val);this.focusShow = false;this.$emit("blur", event);// 根据类型返回值,在event中获取的值理论上讲都是stringthis.$emit("change", this.val);// 失去焦点时参与表单校验if (this.form && this.formItem) {const { validateTrigger } = this.form;if (validateTrigger === "blur") {this.formItem.onFieldChange();}}},/*** 按下键盘的发送键* @param {Object} e*/onConfirm(e) {this.$emit("confirm", this.val);this.$emit("change", this.val);},/*** 清理内容* @param {Object} event*/onClear(event) {this.val = "";// TODO 兼容 vue2this.$emit("input", "");// TODO 兼容 vue2// TODO 兼容 vue3this.$emit("update:modelValue", "");// 点击叉号触发this.$emit("clear");},/*** 去除空格*/trimStr(str, pos = "both") {if (pos === "both") {return str.trim();} else if (pos === "left") {return str.trimLeft();} else if (pos === "right") {return str.trimRight();} else if (pos === "start") {return str.trimStart();} else if (pos === "end") {return str.trimEnd();} else if (pos === "all") {return str.replace(/\s+/g, "");} else if (pos === "none") {return str;}return str;},},
};
</script><style lang="scss">
$uni-error: #e43d33;
$uni-border-1: #dcdfe6 !default;.uni-easyinput {/* #ifndef APP-NVUE */width: 100%;/* #endif */flex: 1;position: relative;text-align: left;color: #333;font-size: 14px;
}.uni-easyinput__content {flex: 1;/* #ifndef APP-NVUE */width: 100%;display: flex;box-sizing: border-box;// min-height: 36px;/* #endif */flex-direction: row;align-items: center;// 处理border动画刚开始显示黑色的问题border-color: #fff;transition-property: border-color;transition-duration: 0.3s;
}.uni-easyinput__content-input {/* #ifndef APP-NVUE */width: auto;/* #endif */position: relative;overflow: hidden;flex: 1;line-height: 1;font-size: 14px;height: 35px;// min-height: 36px;
}.uni-easyinput__placeholder-class {color: #999;font-size: 12px;// font-weight: 200;
}.is-textarea {align-items: flex-start;
}.is-textarea-icon {margin-top: 5px;
}.uni-easyinput__content-textarea {position: relative;overflow: hidden;flex: 1;line-height: 1.5;font-size: 14px;margin: 6px;margin-left: 0;height: 80px;min-height: 80px;/* #ifndef APP-NVUE */min-height: 80px;width: auto;/* #endif */
}.input-padding {padding-left: 10px;
}.content-clear-icon {padding: 0 5px;
}.label-icon {margin-right: 5px;margin-top: -1px;
}// 显示边框
.is-input-border {/* #ifndef APP-NVUE */display: flex;box-sizing: border-box;/* #endif */flex-direction: row;align-items: center;border: 1px solid $uni-border-1;border-radius: 4px;/* #ifdef MP-ALIPAY */overflow: hidden;/* #endif */
}.uni-error-message {position: absolute;bottom: -17px;left: 0;line-height: 12px;color: $uni-error;font-size: 12px;text-align: left;
}.uni-error-msg--boeder {position: relative;bottom: 0;line-height: 22px;
}.is-input-error-border {border-color: $uni-error;.uni-easyinput__placeholder-class {color: mix(#fff, $uni-error, 50%);}
}.uni-easyinput--border {margin-bottom: 0;padding: 10px 15px;// padding-bottom: 0;border-top: 1px #eee solid;
}.uni-easyinput-error {padding-bottom: 0;
}.is-first-border {/* #ifndef APP-NVUE */border: none;/* #endif *//* #ifdef APP-NVUE */border-width: 0;/* #endif */
}.is-disabled {background-color: #f7f6f6;color: #d5d5d5;.uni-easyinput__placeholder-class {color: #d5d5d5;font-size: 12px;}
}
</style>

2.这样已经可以解决光标闪动了,但是在进行表单验证那块可能会出现表单验证不通过的情况(不使用虚拟键盘的),是因为表单验证时,文本框还没有失去焦点,针对这一情况,则可以在验证那块增加sleep,如下

uni-forms.vue改后的代码如下:休眠时间可以自己定义

<template><view class="uni-forms"><form><slot></slot></form></view>
</template><script>import Validator from './validate.js';import {deepCopy,getValue,isRequiredField,setDataValue,getDataValue,realName,isRealName,rawData,isEqual} from './utils.js'// #ifndef VUE3// 后续会慢慢废弃这个方法import Vue from 'vue';Vue.prototype.binddata = function(name, value, formName) {if (formName) {this.$refs[formName].setValue(name, value);} else {let formVm;for (let i in this.$refs) {const vm = this.$refs[i];if (vm && vm.$options && vm.$options.name === 'uniForms') {formVm = vm;break;}}if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');formVm.setValue(name, value);}};// #endif/*** Forms 表单* @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据* @tutorial https://ext.dcloud.net.cn/plugin?id=2773* @property {Object} rules	表单校验规则* @property {String} validateTrigger = [bind|submit|blur]	校验触发器方式 默认 submit* @value bind		发生变化时触发* @value submit	提交时触发* @value blur	  失去焦点时触发* @property {String} labelPosition = [top|left]	label 位置 默认 left* @value top		顶部显示 label* @value left	左侧显示 label* @property {String} labelWidth	label 宽度,默认 65px* @property {String} labelAlign = [left|center|right]	label 居中方式  默认 left* @value left		label 左侧显示* @value center	label 居中* @value right		label 右侧对齐* @property {String} errShowType = [undertext|toast|modal]	校验错误信息提示方式* @value undertext	错误信息在底部显示* @value toast			错误信息toast显示* @value modal			错误信息modal显示* @event {Function} submit	提交时触发* @event {Function} validate	校验结果发生变化触发*/export default {name: 'uniForms',emits: ['validate', 'submit'],options: {virtualHost: true},props: {// 即将弃用value: {type: Object,default () {return null;}},// vue3 替换 value 属性modelValue: {type: Object,default () {return null;}},// 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValuemodel: {type: Object,default () {return null;}},// 表单校验规则rules: {type: Object,default () {return {};}},//校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal]errShowType: {type: String,default: 'undertext'},// 校验触发器方式 默认 bind 取值 [bind|submit]validateTrigger: {type: String,default: 'submit'},// label 位置,默认 left 取值  top/leftlabelPosition: {type: String,default: 'left'},// label 宽度labelWidth: {type: [String, Number],default: ''},// label 居中方式,默认 left 取值 left/center/rightlabelAlign: {type: String,default: 'left'},border: {type: Boolean,default: false}},provide() {return {uniForm: this}},data() {return {// 表单本地值的记录,不应该与传如的值进行关联formData: {},formRules: {}};},computed: {// 计算数据源变化的localData() {const localVal = this.model || this.modelValue || this.valueif (localVal) {return deepCopy(localVal)}return {}}},watch: {// 监听数据变化 ,暂时不使用,需要单独赋值// localData: {},// 监听规则变化rules: {handler: function(val, oldVal) {this.setRules(val)},deep: true,immediate: true}},created() {// #ifdef VUE3let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddataif (!getbinddata) {getApp().$vm.$.appContext.config.globalProperties.binddata = function(name, value, formName) {if (formName) {this.$refs[formName].setValue(name, value);} else {let formVm;for (let i in this.$refs) {const vm = this.$refs[i];if (vm && vm.$options && vm.$options.name === 'uniForms') {formVm = vm;break;}}if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');formVm.setValue(name, value);}}}// #endif// 子组件实例数组this.childrens = []// TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错this.inputChildrens = []this.setRules(this.rules)},methods: {/*** 外部调用方法* 设置规则 ,主要用于小程序自定义检验规则* @param {Array} rules 规则源数据*/setRules(rules) {// TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖this.formRules = Object.assign({}, this.formRules, rules)// 初始化校验函数this.validator = new Validator(rules);},/*** 外部调用方法* 设置数据,用于设置表单数据,公开给用户使用 , 不支持在动态表单中使用* @param {Object} key* @param {Object} value*/setValue(key, value) {let example = this.childrens.find(child => child.name === key);if (!example) return null;this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || [])return example.onFieldChange(this.formData[key]);},/*** 外部调用方法* 手动提交校验表单* 对整个表单进行校验的方法,参数为一个回调函数。* @param {Array} keepitem 保留不参与校验的字段* @param {type} callback 方法回调*/validate(keepitem, callback) {return this.checkAll(this.formData, keepitem, callback);},/*** 外部调用方法* 部分表单校验* @param {Array|String} props 需要校验的字段* @param {Function} 回调函数*/validateField(props = [], callback) {props = [].concat(props);let invalidFields = {};this.childrens.forEach(item => {const name = realName(item.name)if (props.indexOf(name) !== -1) {invalidFields = Object.assign({}, invalidFields, {[name]: this.formData[name]});}});return this.checkAll(invalidFields, [], callback);},/*** 外部调用方法* 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果* @param {Array|String} props 需要移除校验的字段 ,不填为所有*/clearValidate(props = []) {props = [].concat(props);this.childrens.forEach(item => {if (props.length === 0) {item.errMsg = '';} else {const name = realName(item.name)if (props.indexOf(name) !== -1) {item.errMsg = '';}}});},/*** 外部调用方法 ,即将废弃* 手动提交校验表单* 对整个表单进行校验的方法,参数为一个回调函数。* @param {Array} keepitem 保留不参与校验的字段* @param {type} callback 方法回调*/submit(keepitem, callback, type) {for (let i in this.dataValue) {const itemData = this.childrens.find(v => v.name === i);if (itemData) {if (this.formData[i] === undefined) {this.formData[i] = this._getValue(i, this.dataValue[i]);}}}if (!type) {console.warn('submit 方法即将废弃,请使用validate方法代替!');}return this.checkAll(this.formData, keepitem, callback, 'submit');},sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));},// 校验所有async checkAll(invalidFields, keepitem, callback, type) {//等待uni-easyinput的失去光标事件完成,才验证数据是否填写(uni-easyinput的bug修复光标闪动,将modelvalue的值放在失去光标的时候更新)console.log('开始休眠');await this.sleep(500); // 休眠 0.5 秒console.log('休眠结束');// 不存在校验规则 ,则停止校验流程if (!this.validator) returnlet childrens = []// 处理参与校验的item实例for (let i in invalidFields) {const item = this.childrens.find(v => realName(v.name) === i)if (item) {childrens.push(item)}}// 如果validate第一个参数是funciont ,那就走回调if (!callback && typeof keepitem === 'function') {callback = keepitem;}let promise;// 如果不存在回调,那么使用 Promise 方式返回if (!callback && typeof callback !== 'function' && Promise) {promise = new Promise((resolve, reject) => {callback = function(valid, invalidFields) {!valid ? resolve(invalidFields) : reject(valid);};});}let results = [];// 避免引用错乱 ,建议拷贝对象处理let tempFormData = JSON.parse(JSON.stringify(invalidFields))// 所有子组件参与校验,使用 for 可以使用  awiatfor (let i in childrens) {const child = childrens[i]let name = realName(child.name);const result = await child.onFieldChange(tempFormData[name]);if (result) {results.push(result);// toast ,modal 只需要执行第一次就可以if (this.errShowType === 'toast' || this.errShowType === 'modal') break;}}if (Array.isArray(results)) {if (results.length === 0) results = null;}if (Array.isArray(keepitem)) {keepitem.forEach(v => {let vName = realName(v);let value = getDataValue(v, this.localData)if (value !== undefined) {tempFormData[vName] = value}});}// TODO submit 即将废弃if (type === 'submit') {this.$emit('submit', {detail: {value: tempFormData,errors: results}});} else {this.$emit('validate', results);}// const resetFormData = rawData(tempFormData, this.localData, this.name)let resetFormData = {}resetFormData = rawData(tempFormData, this.name)callback && typeof callback === 'function' && callback(results, resetFormData);if (promise && callback) {return promise;} else {return null;}},/*** 返回validate事件* @param {Object} result*/validateCheck(result) {this.$emit('validate', result);},_getValue: getValue,_isRequiredField: isRequiredField,_setDataValue: setDataValue,_getDataValue: getDataValue,_realName: realName,_isRealName: isRealName,_isEqual: isEqual}};
</script><style lang="scss">.uni-forms {}
</style>

 方案二:

uni-easyinput组件不要使用v-model这种双向绑定的,直接使用value并通过@blur来监听失去焦点,当失去焦点时,则通过ref的方式去获取文本框的值

blur(){
this.formData.supplierBatch=this.$refs.easyinput.val
}

这篇关于uni-easyinput连续输入出现闪动解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/221725

相关文章

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas

Mysql DATETIME 毫秒坑的解决

《MysqlDATETIME毫秒坑的解决》本文主要介绍了MysqlDATETIME毫秒坑的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 今天写代码突发一个诡异的 bug,代码逻辑大概如下。1. 新增退款单记录boolean save = s

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

解决Cron定时任务中Pytest脚本无法发送邮件的问题

《解决Cron定时任务中Pytest脚本无法发送邮件的问题》文章探讨解决在Cron定时任务中运行Pytest脚本时邮件发送失败的问题,先优化环境变量,再检查Pytest邮件配置,接着配置文件确保SMT... 目录引言1. 环境变量优化:确保Cron任务可以正确执行解决方案:1.1. 创建一个脚本1.2. 修

Mysql8.0修改配置文件my.ini的坑及解决

《Mysql8.0修改配置文件my.ini的坑及解决》使用记事本直接编辑my.ini文件保存后,可能会导致MySQL无法启动,因为MySQL会以ANSI编码读取该文件,解决方法是使用Notepad++... 目录Myhttp://www.chinasem.cnsql8.0修改配置文件my.ini的坑出现的问题

SpringBoot项目删除Bean或者不加载Bean的问题解决

《SpringBoot项目删除Bean或者不加载Bean的问题解决》文章介绍了在SpringBoot项目中如何使用@ComponentScan注解和自定义过滤器实现不加载某些Bean的方法,本文通过实... 使用@ComponentScan注解中的@ComponentScan.Filter标记不加载。@C

MySQL8.0找不到my.ini如何解决

《MySQL8.0找不到my.ini如何解决》在配置MySQL主从复制时,发现找不到my.ini配置文件,通过检查路径和打开隐藏文件夹,最终在C:ProgramDataMySQLMySQLSer... 目录问题描述解决方法总结问题描述今天在配置mysql主从复制的时候发现,找不到my.ini这个配置文件。

Mybatis提示Tag name expected的问题及解决

《Mybatis提示Tagnameexpected的问题及解决》MyBatis是一个开源的Java持久层框架,用于将Java对象与数据库表进行映射,它提供了一种简单、灵活的方式来访问数据库,同时也... 目录概念说明MyBATis特点发现问题解决问题第一种方式第二种方式问题总结概念说明MyBatis(原名

oracle数据库索引失效的问题及解决

《oracle数据库索引失效的问题及解决》本文总结了在Oracle数据库中索引失效的一些常见场景,包括使用isnull、isnotnull、!=、、、函数处理、like前置%查询以及范围索引和等值索引... 目录oracle数据库索引失效问题场景环境索引失效情况及验证结论一结论二结论三结论四结论五总结ora