Vue2 में बहस कैसे लागू करें?


143

मेरे पास एक Vue टेम्पलेट में एक सरल इनपुट बॉक्स है और मैं इस तरह से कम या ज्यादा बहस का उपयोग करना चाहूंगा:

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

हालाँकि Vue 2 मेंdebounce संपत्ति को हटा दिया गया है । सिफारिश केवल यह कहती है: "वी-ऑन का उपयोग करें: इनपुट + 3 पार्टी का टीकाकरण समारोह"।

आप इसे सही तरीके से कैसे लागू करते हैं?

मैंने इसे लॉश , वी-ऑन: इनपुट और वी-मॉडल का उपयोग करके लागू करने की कोशिश की है , लेकिन मैं सोच रहा हूं कि क्या अतिरिक्त चर के बिना ऐसा करना संभव है।

टेम्पलेट में:

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

स्क्रिप्ट में:

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

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

बाद में computedप्रॉप्स में फ़िल्टर का उपयोग किया जाता है ।


1
यह एक कोशिश करो stackoverflow.com/questions/41230343/…
sobolevn

3
मैं ध्यान से पढ़ने का सुझाव दूंगा
Marek Urbanowicz

3
: वहाँ गाइड में एक उदाहरण है vuejs.org/v2/guide/computed.html#Watchers
Bengt

जवाबों:


158

मैं उपयोग कर रहा हूँ debounce NPM पैकेज और इस तरह से लागू किया:

<input @input="debounceInput">

methods: {
    debounceInput: debounce(function (e) {
      this.$store.dispatch('updateInput', e.target.value)
    }, config.debouncers.default)
}

सवाल में दर्ज और उदाहरण का उपयोग करते हुए , कार्यान्वयन इस तरह दिखता है:

<input v-on:input="debounceInput">

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

10
इसके लिए धन्यवाद। मुझे कुछ अन्य Vue डॉक्स में एक समान उदाहरण मिला: vuejs.org/v2/examples/index.html ( मार्कडाउन एडिटर)
MartinTeeVarga

5
जब पृष्ठ पर कई घटक उदाहरण होते हैं, तो प्रस्तावित समाधान में समस्या होती है। समस्या का वर्णन और समाधान यहाँ प्रस्तुत किया गया है: forum.vuejs.org/t/issues-with-vuejs-component-and-debounce/7224/…
Valera

e.currentTarget को इस तरह से लिखने के लिए ओवरराइट किया गया है
ness-EE

1
v-model=your_input_variableइनपुट में और आपके व्रत में जोड़ने की सिफारिश करेगा data। इसलिए आप पर भरोसा नहीं करते हैं, e.targetलेकिन Vue का उपयोग करें ताकि आप this.your_input_variableइसके बजाय एक्सेस कर सकेंe.target.value
DominikAngerer

1
ES6 का उपयोग करने वालों के लिए, यहां अनाम फ़ंक्शन के उपयोग पर जोर देना महत्वपूर्ण है: यदि आप एक तीर फ़ंक्शन का उपयोग करते हैं तो आप फ़ंक्शन के thisभीतर नहीं पहुंच पाएंगे ।
पॉल्सन

68

इसमें बहस का काम methodsकरना मुसीबत बन सकता है। इसलिए इसके बजाय:

// Bad
methods: {
  foo: _.debounce(function(){}, 1000)
}

आप कोशिश कर सकते हैं:

// Good
created () {
  this.foo = _.debounce(function(){}, 1000);
}

यह एक मुद्दा बन जाता है अगर आपके पास घटक के कई उदाहरण हैं - जिस तरह dataसे एक फ़ंक्शन होना चाहिए जो एक वस्तु लौटाता है। यदि उन्हें स्वतंत्र रूप से कार्य करना चाहिए तो प्रत्येक उदाहरण को अपने स्वयं के डिब्यू फ़ंक्शन की आवश्यकता होती है।

यहाँ समस्या का एक उदाहरण है:

Vue.component('counter', {
  template: '<div>{{ i }}</div>',
  data: function(){
    return { i: 0 };
  },
  methods: {
    // DON'T DO THIS
    increment: _.debounce(function(){
      this.i += 1;
    }, 1000)
  }
});


new Vue({
  el: '#app',
  mounted () {
    this.$refs.counter1.increment();
    this.$refs.counter2.increment();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

<div id="app">
  <div>Both should change from 0 to 1:</div>
  <counter ref="counter1"></counter>
  <counter ref="counter2"></counter>
</div>


1
क्या आप बता सकते हैं कि तरीकों में बहस करना क्यों परेशानी भरा हो सकता है?
मार्टिनटैरगा

12
देखें उदाहरण लिंक लिंक सड़ने के लिए प्रवण हैं। उत्तर में समस्या की व्याख्या करना बेहतर है - यह पाठकों के लिए अधिक मूल्यवान बना देगा।
मार्टिनटैरगा

बहुत-बहुत धन्यवाद, मेरे पास यह समझने का एक बुरा समय था कि कंसोल पर प्रदर्शित डेटा सही क्यों था, लेकिन ऐप पर लागू नहीं किया गया ...

@ sm4 क्योंकि आपके वांछित फ़ंक्शन के लिए समान साझा किए गए उदाहरण का उपयोग करने के बजाय, यह प्रत्येक बार इसे पुनः बनाता है, इस प्रकार मुख्य रूप से बहस के उपयोग को मारता है।
माइक शीव

1
बस इसे अपने में जोड़ें data()
सू-औ ह्वांग

45

2020 में अपडेट किया गया

विकल्प 1: पुन: प्रयोज्य, कोई डिप्स नहीं

(अनुशंसित यदि आपकी परियोजना में एक से अधिक बार आवश्यकता हो)

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: इन-कंपोनेंट, कोई डिप्स नहीं

(एक बार या छोटे प्रोजेक्ट में उपयोग करने पर अनुशंसित)

Component.vue

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

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

Codepen


4
आप असली हीरो
एश्टनियन

4
मैं इस विकल्प को पसंद करता हूं क्योंकि मुझे कोड की 11 लाइनों के लिए शायद एक npm पैकेज की आवश्यकता नहीं है ....
बेन विंडिंग

3
यह चिह्नित उत्तर होना चाहिए, यह वास्तव में अच्छी तरह से काम करता है और लगभग कोई स्थान नहीं लेता है। धन्यवाद!
अलेक्जेंडर क्लूड

29

बिना किसी लाग-लपेट के बहुत ही सरल

  handleScroll: function() {
   if (this.timeout) clearTimeout(this.timeout); 
   this.timeout = setTimeout(() => {
     // your action
   }, 200);
  }

4
जितना मुझे लताश पसंद है, यह स्पष्ट रूप से अनुगामी बहस के लिए सबसे अच्छा जवाब है। समझने के साथ ही लागू करने के लिए सबसे आसान।
माइकल ने

2
destroyed() { clearInterval(this.timeout) }नष्ट होने के बाद टाइमआउट न करने के लिए जोड़ना भी एक अच्छी बात है ।
पिकिलॉन

13

मुझे एक ही समस्या थी और यहाँ एक समाधान है जो प्लगइन्स के बिना काम करता है।

चूंकि <input v-model="xxxx">बिल्कुल वैसा ही है

<input
   v-bind:value="xxxx"
   v-on:input="xxxx = $event.target.value"
>

(स्रोत)

मुझे लगा कि मैं xxxx के असाइनमेंट पर एक डेबिट फ़ंक्शन सेट कर सकता हूं xxxx = $event.target.value

इस तरह

<input
   v-bind:value="xxxx"
   v-on:input="debounceSearch($event.target.value)"
>

विधि:

debounceSearch(val){
  if(search_timeout) clearTimeout(search_timeout);
  var that=this;
  search_timeout = setTimeout(function() {
    that.xxxx = val; 
  }, 400);
},

1
यदि आपके इनपुट क्षेत्र में भी एक @input="update_something"क्रिया थी, तो इसके बाद कॉल करेंthat.xxx = val that.update_something();
नियॉन

1
मेरे तरीकों के अनुभाग में मैंने थोड़ा अलग वाक्यविन्यास का उपयोग किया जो मेरे लिए काम करता था:debounceSearch: function(val) { if (this.search_timeout) clearTimeout(this.search_timeout); var that=this; this.search_timeout = setTimeout(function() { that.thread_count = val; that.update_something(); }, 500); },
Neon22

यह ठीक है यदि आप एक या बहुत कम उदाहरण हैं, जहां आपको इनपुट की आलोचना करने की आवश्यकता है। हालाँकि, आपको जल्दी से पता चल जाएगा कि आपको इसे किसी लाइब्रेरी या ऐसे ही ले जाने की ज़रूरत है, अगर ऐप बढ़ता है और इस कार्यक्षमता की कहीं और ज़रूरत है। अपना कोड DRY रखें।
कोरस

5

कृपया ध्यान दें कि मैंने यह उत्तर स्वीकृत उत्तर से पहले पोस्ट किया है। यह सही नहीं है। यह प्रश्न में समाधान से सिर्फ एक कदम आगे है। मैंने लेखक के कार्यान्वयन और मेरे द्वारा उपयोग किए गए अंतिम कार्यान्वयन दोनों को दिखाने के लिए स्वीकृत प्रश्न को संपादित किया है।


टिप्पणियों और लिंक किए गए माइग्रेशन दस्तावेज़ के आधार पर , मैंने कोड में कुछ बदलाव किए हैं:

टेम्पलेट में:

<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)।


क्या यह debounceInput()प्रत्येक परिवर्तन के लिए दो बार कॉल नहीं करेगा? v-on:इनपुट परिवर्तन और कॉल डिबेट का पता लगाएगा, और क्योंकि मॉडल बाध्य है, searchInput का घड़ी फ़ंक्शन ALSO कॉल करेगा debounceInput... सही है?
मिक्स 3 डी

@ mix3d इस उत्तर पर विचार न करें। यह सिर्फ मेरी जांच थी जिसे मैं सवाल में नहीं डालना चाहता था। आप सबसे अधिक सही हैं। स्वीकृत उत्तर की जांच करें। यह सही है और मैंने इसे प्रश्न का मिलान करने के लिए संपादित किया है।
मार्टिनटेगा

मेरी गलती ... मुझे नहीं पता था कि आपने अपने सवाल का जवाब दिया था, हा!
मिक्स 3 डी

5

यदि आपको इसके लिए बहुत न्यूनतम दृष्टिकोण की आवश्यकता है, तो मैंने एक (मूल रूप से vuejs- युक्तियों से आईई का समर्थन करने के लिए कांटा बनाया) जो यहां उपलब्ध है: 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>

संभवतः यह 100+ वोट-अप के साथ एक स्वीकृत समाधान होना चाहिए। ओपी ने इस तरह के एक कॉम्पैक्ट समाधान के लिए कहा, और यह अच्छी तरह से बहस के तर्क को कम कर देता है।
बार्नी

1

मामले में आपको लॉश के debounceकार्य के साथ एक गतिशील देरी लागू करने की आवश्यकता है :

props: {
  delay: String
},

data: () => ({
  search: null
}),

created () {
     this.valueChanged = debounce(function (event) {
      // Here you have access to `this`
      this.makeAPIrequest(event.target.value)
    }.bind(this), this.delay)

},

methods: {
  makeAPIrequest (newVal) {
    // ...
  }
}

और टेम्पलेट:

<template>
  //...

   <input type="text" v-model="search" @input="valueChanged" />

  //...
</template>

ध्यान दें: ऊपर दिए गए उदाहरण में मैंने खोज इनपुट का एक उदाहरण बनाया है जो एपीआई को कस्टम विलंब के साथ कॉल कर सकता है जो इसमें प्रदान किया गया हैprops


1

हालांकि यहां बहुत सारे उत्तर पहले से ही सही हैं, अगर कोई त्वरित समाधान की तलाश में है तो मेरे पास इसके लिए एक निर्देश है। https://www.npmjs.com/package/vue-lazy-input

यह @input और v- मॉडल पर लागू होता है, कस्टम घटकों और DOM तत्वों, डिब्यूज़ और थ्रॉटल का समर्थन करता है।

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>


0

यदि आप Vue का उपयोग कर रहे हैं, तो आप v.model.lazyइसके बजाय उपयोग भी कर सकते हैं , debounceलेकिन याद रखें v.model.lazyकि हमेशा काम नहीं करेगा क्योंकि Vue इसे कस्टम घटकों के लिए सीमित करता है।

कस्टम घटकों के लिए आपको :valueसाथ में उपयोग करना चाहिए@change.native

<b-input :value="data" @change.native="data = $event.target.value" ></b-input>


0

यदि आप डिबैंस फंक्शन के निष्पादन को कुछ क्लास मेथड में स्थानांतरित कर सकते हैं, तो आप डेकोरेटर्स का उपयोग बर्तन-डेकोरेटर्स लिब ( npm install --save utils-decorators) से कर सकते हैं:

import {debounce} from 'utils-decorators';

class SomeService {

  @debounce(500)
  getData(params) {
  }
}

-1

हम जेएस कोड की कुछ पंक्तियों का उपयोग करके कर सकते हैं:

if(typeof window.LIT !== 'undefined') {
      clearTimeout(window.LIT);
}

window.LIT = setTimeout(() => this.updateTable(), 1000);

सरल उपाय! सही काम! आशा है, आप लोगों के लिए मददगार होगी।


2
सुनिश्चित करें ... यदि आप वैश्विक स्थान को प्रदूषित करना चाहते हैं और इसे बनाते हैं तो एक बार में केवल 1 तत्व ही इसका उपयोग कर सकता है। यह एक भयानक जवाब है।
हाइब्रिड वेब देव

-1
 public debChannel = debounce((key) => this.remoteMethodChannelName(key), 200)

Vue-संपत्ति-डेकोरेटर


2
क्या आप इस समाधान के बारे में अधिक जानकारी जोड़ सकते हैं?
Rocha

2
कृपया थोड़ा और विस्तार करें। इसके अलावा, ध्यान दें कि यह एक पुराना धागा है जिसमें अच्छी तरह से स्थापित उत्तर दिए गए हैं, ताकि आप स्पष्ट कर सकें कि समस्या के लिए आपका समाधान अधिक उपयुक्त कैसे है?
jpnadas

यदि आप स्पष्टीकरण की आपूर्ति करते हैं तो यह अधिक मदद करता है कि यह पसंदीदा समाधान क्यों है और बताएं कि यह कैसे काम करता है। हम शिक्षित करना चाहते हैं, न कि केवल कोड प्रदान करना।
टिन मैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.