uniapp input 数据更新 视图没有更新

今天碰到一个场景,在uniapp中,定义了一个input输入框,输入框被限制只能输入数字,
我用了v-model进行双向数据绑定(值为inputValue),并且在input事件中,对数据进行了处理,
最后将处理后的数据赋值给inputValue,经过日志打印会发现,inputValue的值已经改变了,
但是页面上展示的数据仍然没有改变
比如说,我先输入5,再输入a,此时页面展示还是5a但是我打印出来的数据已经是5了,
更神奇的是,当我再输入一个5时,此时页面视图改变,成55

代码片段

// html 部分
<input
  v-model="inputValue"
  @input="handleChange"
/>

// js部分
handleChange(e) {
  let currentvalue = e.target.value; // 这是当前获取到的值
  console.log('value', e.target.value);

  let value = currentvalue.replace(/\D/g, ''); // 处理非数字的数据

  this.inputValue = value;
  console.log('this.inputValue', this.inputValue) // 这里输出的结果显示值已经变成了处理后的结果
}

先说解决方案

解决方案

在进行赋值操作时,在$nextTick或者setTimeout的回调中,进行赋值操作
handleChange(e) {
  let currentvalue = e.target.value; // 这是当前获取到的值
  console.log('value', e.target.value);

  let value = currentvalue.replace(/\D/g, ''); // 处理非数字的数据
  // 方法一
  this.$nextTick(() => {
      this.inputValue = value;
      console.log('this.inputValue', this.inputValue) // 这里输出的结果显示值已经变成了处理后的结果
  })
  // 方法二
  setTimeOut(() => {
      this.inputValue = value;
      console.log('this.inputValue', this.inputValue) // 这里输出的结果显示值已经变成了处理后的结果
  },0)
}

分析

以下分析内容不一定正确,仅供参考

首先分析为什么原来的方法视图不会更新

  • 首先我们要知道,vue的视图更新机制,也就是说当我们修改了数据的时候,他并不会立即去进行视图的更新,而是将更新操作放到下一个事件循环中,所以视图的更新是异步的。
  • 当任务队列执行到更新操作时,会拿当前的数据和原始的数据进行对比,如果有修改,就去调用视图刷新的方法。
  • 所以当我们v-model修改数据的时候,比如我原先是5,我再输入a的时候,vue会将一个更新任务放到任务队列中等待执行,但是因为我在input事件中,利用replace方法将5a变成5,同时将值又赋给了inputValue,所以当更新任务执行的时候,会发现,原始值5和现在的值都是5,并没有改变,所以不会触发视图更新的方法,所以页面上依旧保持着是5a,但是我们的值已经改变了

接着我们来分析原先的情况下,为什么在最后输入数字又会导致视图更新了

  • 当我再输入一个5时,此时更新任务中,原始值为5,现在的值为55,所以会触发视图更新,解决了我们碰到的神奇的情况。

最后我们来分析为什么将赋值操作放在nextTick中会起作用

  • 而当我们将赋值操作放到nextTick或者setTimeout中时,他们会在当前视图更新完成后执行里面的回调,所以在v-model改变数据为5a后,视图会先去更新一遍,此时值为5a。
  • 然后在nextTick中,我们再去改变inputValue的值时,会再向任务队列里添加一个更新任务,此时取到的原始值就是5a,目前的值就是5,所以会触发视图的更新操作,于是完成了视图的更新

总结

  • 视图的更新是异步的,在更新时会比较原先的值和现在的值是否相等,不相等的话进行视图更新
  • 所以如果赋值操作是同步的话,就很容易造成两个值对比时相等的情况,从而造成视图不更新,解决方案就是进行异步赋值,即使用nextTick或者setTimeout。

其他方案

之前在网上还看到其他几种方案,我试了都没起作用,这里罗列出来,仅供参考
  • 1、有的说是v-model绑定的层级太深了,比如说**v-model=”data.person.name”**这种,解决方法就是定义一个简单的变量如inputValue来接受他的值,再通过改变inputValue的值来改变视图
  • 2、有的说是v-model的问题,可以通过自己实现双向绑定的方式来解决,比如:value=”inputValue”,然后在input事件中对value赋值

原文链接:https://juejin.cn/post/7234058802743427132 作者:奈何天丶

(1)
上一篇 2023年5月18日 上午10:26
下一篇 2023年5月18日 上午10:36

相关推荐

发表评论

登录后才能评论