输入值在使用v-去抖动进行突变时被覆盖

时间:2019-05-21 01:20:50

标签: vue.js vuejs2 debounce v-debounce

考虑以下示例:

https://codesandbox.io/s/vdebounce-input-override-ej4nz

它是大型应用程序的简化版本(大部分为模拟版本),它使用Observables根据用户输入从多个API中获取过滤结果。我需要消除输入的抖动。
在应用程序中,去抖动值较大,因此该问题不太明显,但在示例中我降低了该值,以使问题更容易发现。我还尝试模拟服务器响应时间的随机性。

问题是,每当我收到回复时,如果我输入的内容会丢失几个字符,具体取决于我输入的速度。
如果我删除了v-debounce指令(或.lazy修饰符),问题就解决了,但是没有反跳。

我也在v-debounce回购中提出了它。

我知道我可以完全抛弃v-debounce并在手表内使用lodash的反跳功能,但我希望我不必这样做(因为v-debounce应该可以满足Vue,对!!)。到目前为止,我一直尝试将内容保持在“ Vue”状态。


重要编辑 :(回答后),看来有两个软件包定义了v-debounce指令。好人在这里:npmgithub

npm i vue-debounce

我使用的是v-debounce,它会覆盖输入。

1 个答案:

答案 0 :(得分:1)

了解问题

您遇到的问题是标记渲染事件反跳之间的相互作用(这可能是v反跳问题,或者预期的行为观点可能会有所不同) :

  • 您要取消对输入元素上的 change事件的触发
    • 已去抖动的事件会在呼叫时用输入的值触发 (也就是说,已去抖动的呼叫中没有呼叫数据的存储空间)
  • 分别(在每次防抖动的实际调用中)您都有一个异步操作(模拟服务器搜索),以更改组件的状态,并触发组件重新渲染
    • 此重新渲染将检查整个组件DOM,并“更正”它认为错误的输入值
  • 在异步操作后触发去抖动的更改事件时,它会以当前DOM输入值触发,该值现在已经过时了(如果您继续键入,甚至会有些混乱)
  • >

可能的解决方案

这里的主要问题是应该跟踪实际的搜索值。您要取消搜索操作的反作用力,而不是值更改本身(当然也不是输入更改事件)

处理自我反跳

Here is an alternative to your app,执行以下操作:

  • 保留一个v模型-search-不反跳
  • 在更改所述v模型时:
    • 如果当前正在进行搜索,立即取消搜索
    • 触发一个去抖动的搜索操作(该操作仅在键入停止时才开始)
[...]
  mounted() {
    this.debouncedSearch = _.debounce(this.search, 500);
  },
  methods: {
    search() {
      this.loading = true;
      this.$searchTimeout = setTimeout(() => {
        store.albums = albums.filter(
          album => album.title.indexOf(this.term) > -1
        );
        store.searchTerm = this.term;
        this.loading = false;
      }, Math.floor(Math.random() * 1000 + 300));
    }
  },
  watch: {
    term() {
      if (this.$searchTimeout) {
        this.loading = false;
        clearTimeout(this.$searchTimeout);
        delete this.$searchTimeout;
      }
      this.debouncedSearch();
    }
  }

不影响v-model的反跳指令

Here is another solution使用了自定义指令,该指令可对输入事件处理程序进行反跳操作,不会弄乱与change的v模型绑定

在此应用程序:

  • 保留一个v模型-search-不反跳
    • 更改所述v模型后,如果当前正在进行搜索,立即取消
  • 使用v-debounce指令触发去抖动的搜索操作(实际上只会在键入停止键时开始)
<input 
  v-model="term" 
  v-debounce="{ delay: 500, handler: search}" 
  @input="clearSearch">