我在Vue模板中有一个简单的输入框,我想使用debounce或多或少像这样:

<input type="text" v-model="filterKey" debounce="500">

然而,在Vue 2中debounce属性已被弃用。建议只说:“使用v-on:输入+第三方反弹功能”。

如何正确地实现它?

我尝试使用lodash, v-on:input和v-model来实现它,但我想知道是否有可能没有额外的变量。

在模板:

<input type="text" v-on:input="debounceInput" v-model="searchInput">

在脚本:

data: function () {
  return {
    searchInput: '',
    filterKey: ''
  }
},

methods: {
  debounceInput: _.debounce(function () {
    this.filterKey = this.searchInput;
  }, 500)
}

然后在计算道具中使用过滤键。


当前回答

虽然这里几乎所有的答案都是正确的,如果有人正在寻找一个快速的解决方案,我有一个指令。 https://www.npmjs.com/package/vue-lazy-input

它适用于@input和v-model,支持自定义组件和DOM元素,debounce和throttle。

Vue.use(VueLazyInput) new Vue({ el: '#app', data() { return { val: 42 } }, methods:{ onLazyInput(e){ console.log(e.target.value) } } }) <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <script src="https://unpkg.com/lodash/lodash.min.js"></script><!-- dependency --> <script src="https://unpkg.com/vue-lazy-input@latest"></script> <div id="app"> <input type="range" v-model="val" @input="onLazyInput" v-lazy-input /> {{val}} </div>

其他回答

如果你需要一个非常简约的方法,我做了一个(最初从vuejs-tips分叉也支持IE),可在这里:https://www.npmjs.com/package/v-debounce

用法:

<input v-model.lazy="term" v-debounce="delay" placeholder="Search for something" />

然后在你的组件中:

<script>
export default {
  name: 'example',
  data () {
    return {
      delay: 1000,
      term: '',
    }
  },
  watch: {
    term () {
      // Do something with search term after it debounced
      console.log(`Search term changed to ${this.term}`)
    }
  },
  directives: {
    debounce
  }
}
</script>

下面是一个Vue 2组件示例,演示了如何使用debounce。

<template>
  <div>
    <v-btn @click="properDebounceMyMethod">Proper debounce</v-btn>
    <v-btn @click="notWorkingDebounceMyMethod">!debounce</v-btn>
    <v-btn @click="myMethod">normal call</v-btn>
  </div>
</template>

<script lang="ts" >
import { defineComponent } from '@vue/composition-api';
import { debounce } from 'lodash';

export default defineComponent({
  name: 'DebounceExample',
  created() {
    // debounce instance method dynamically on created hook
    this.properDebounceMyMethod = debounce(this.properDebounceMyMethod, 500);
  },
  methods: {
    properDebounceMyMethod(){
      this.myMethod();
    },
    notWorkingDebounceMyMethod() {
      debounce(this.myMethod, 500);
    },
    myMethod() {
      console.log('hi from my method');
    },
  }
});
</script>

请注意,我在接受的答案之前发布了这个答案。这不是 正确的。这只是从解决方案向前迈进了一步 的问题。我编辑了已接受的问题,以显示作者的实现和我使用的最终实现。


基于注释和链接迁移文档,我对代码做了一些更改:

在模板:

<input type="text" v-on:input="debounceInput" v-model="searchInput">

在脚本:

watch: {
  searchInput: function () {
    this.debounceInput();
  }
},

设置过滤器键的方法保持不变:

methods: {
  debounceInput: _.debounce(function () {
    this.filterKey = this.searchInput;
  }, 500)
}

这看起来好像少了一个调用(只是v-model,而不是v-on:input)。

选项1:可重复使用,无deps

-如果在你的项目中需要不止一次,建议使用

/ helpers.js

export function debounce (fn, delay) {
  var timeoutID = null
  return function () {
    clearTimeout(timeoutID)
    var args = arguments
    var that = this
    timeoutID = setTimeout(function () {
      fn.apply(that, args)
    }, delay)
  }
}

/ Component.vue

<script>
  import {debounce} from './helpers'

  export default {
    data () {
      return {
        input: '',
        debouncedInput: ''
      }
    },
    watch: {
      input: debounce(function (newVal) {
        this.debouncedInput = newVal
      }, 500)
    }
  }
</script>

Codepen


选项2:组件内,也没有deps

-建议一次性使用或用于小型项目

/ Component.vue

<template>
    <input type="text" v-model="input" />
</template>

<script>
  export default {
    data: {
        timeout: null,
        debouncedInput: ''
    },
    computed: {
     input: {
        get() {
          return this.debouncedInput
        },
        set(val) {
          if (this.timeout) clearTimeout(this.timeout)
          this.timeout = setTimeout(() => {
            this.debouncedInput = val
          }, 300)
        }
      }
    }
  }
</script>

Codepen

短版本使用箭头函数,默认延迟值

文件:debounce.js in ex: (import debounce from '../../跑龙套/防反跳”)

export default function (callback, delay=300) {
    let timeout = null
    return (...args) => {
        clearTimeout(timeout)
        const context = this
        timeout = setTimeout(() => callback.apply(context, args), delay)
    }
}

2 Mixin选项

文件:debounceMixin.js

export default {
  methods: {
    debounce(func, delay=300) {
      let debounceTimer;
      return function() {
       // console.log("debouncing call..");
        const context = this;
        const args = arguments;
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => func.apply(context, args), delay);
        // console.log("..done");
      };
    }
  }
};

在vueComponent中使用:

<script>
  import debounceMixin from "../mixins/debounceMixin";
  export default {
   mixins: [debounceMixin],
        data() {
            return {
                isUserIdValid: false,
            };
        },
        mounted() {
        this.isUserIdValid = this.debounce(this.checkUserIdValid, 1000);
        },
    methods: {
        isUserIdValid(id){
        // logic
        }
  }
</script>

另一个选项,例子

Vue搜索输入反弹