Vue2 এ ডেবিউন কীভাবে বাস্তবায়ন করবেন?


143

আমার কাছে একটি ভ্যু টেম্পলেটে একটি সহজ ইনপুট বাক্স রয়েছে এবং আমি কম-বেশি এর মতো ডেবিউনটি ব্যবহার করতে চাই:

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

তবে debounceসম্পত্তি ভ্যু 2 এ অবচয় করা হয়েছে । সুপারিশটি কেবলমাত্র বলে: "ভি-অন ব্যবহার করুন: ইনপুট + তৃতীয় পক্ষের ডেবিউন ফাংশন"।

আপনি কীভাবে এটি সঠিকভাবে প্রয়োগ করবেন?

আমি লোড্যাশ , ভি-অন: ইনপুট এবং ভি-মডেল ব্যবহার করে এটি বাস্তবায়নের চেষ্টা করেছি , তবে আমি ভাবছি অতিরিক্ত ভেরিয়েবল ছাড়া এটি করা সম্ভব কিনা।

টেমপ্লেটে:

<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
আমি সাবধানে পড়ার পরামর্শ দেব: vuejs.org/v2/guide/…
মারেক

উত্তর:


158

আমি ডেবিউন এনপিএম প্যাকেজটি ব্যবহার করছি এবং এর মতো প্রয়োগ করা হচ্ছে:

<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
এর জন্য ধন্যবাদ. আমি অন্য কয়েকটি ভ্যু ডক্সে অনুরূপ উদাহরণটি পেয়েছি: vuejs.org/v2/example/index.html ( মার্কডাউন সম্পাদক)
মার্টিনটী ভার্গা

5
পৃষ্ঠায় বেশ কয়েকটি উপাদান দৃষ্টান্ত উপস্থিত থাকলে প্রস্তাবিত সমাধানটিতে সমস্যা হয়। সমস্যা বর্ণনা করা হয়েছে এবং সমাধান এখানে উপস্থাপন: forum.vuejs.org/t/issues-with-vuejs-component-and-debounce/7224/...
ভালেরা

ই-কর্নার টার্গেটটি এইভাবে বাতিল করতে ওভাররাইট করা হয়েছে
নেস-ইই

1
v-model=your_input_variableইনপুটটিতে এবং আপনার বিবেচনায় একটি যুক্ত করার পরামর্শ দিবে data। সুতরাং আপনি নির্ভর করেন না e.targetতবে this.your_input_variablee.target.value
ভ্যু

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
উদাহরণ লিঙ্কগুলি লিঙ্ক-পচা প্রবণ হয় দেখুন। উত্তরে সমস্যাটি ব্যাখ্যা করা আরও ভাল - এটি পাঠকদের জন্য এটি আরও মূল্যবান করে তুলবে।
মার্টিনটীভার্গা

ধন্যবাদ আপনাকে খুব মিলছে, কনসোলে প্রদর্শিত ডেটা সঠিক ছিল তবে অ্যাপটিতে প্রয়োগ করা হয়নি কেন তা বোঝার চেষ্টা করার সময় আমার খুব খারাপ সময় হয়েছিল ...

@ এসএম 4 কারণ আপনার পছন্দসই ফাংশনটির জন্য একই ভাগ করা উদ্বোধনী উদাহরণটি ব্যবহার না করে এটি প্রতিবার এটি পুনরায় তৈরি করে, যার ফলে মূলত ডাবনসের ব্যবহারকে হত্যা করা হয়।
মাইক শেওয়ার্ড

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: ইন-উপাদান, কোনও Deps

(একবারে বা ছোট প্রকল্পে ব্যবহার করা হলে প্রস্তাবিত)

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 লাইনের কোডের জন্য আমার সম্ভবত এনপিএম প্যাকেজের প্রয়োজন নেই ....
বেন উইন্ডিং

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 = $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); },
নিয়ন

এটি ঠিক আছে যদি আপনার এক বা খুব কম উদাহরণ থাকে যেখানে আপনাকে ইনপুট ডাবনো করতে হবে। যাইহোক, আপনি দ্রুত বুঝতে পারবেন আপনার যদি অ্যাপ্লিকেশনটি বৃদ্ধি পায় এবং অন্য কোথাও এই কার্যকারিতাটির প্রয়োজন হয় তবে আপনাকে এটি একটি লাইব্রেরিতে বা অনুরূপ স্থানান্তরিত করতে হবে। আপনার কোডটি 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:ইনপুট পরিবর্তনগুলি সনাক্ত করবে এবং কল ডিবেউন সনাক্ত করবে, এবং মডেলটি সীমাবদ্ধ থাকায় অনুসন্ধান ইনপুটটির ঘড়ির কাজটিও কি ডাকবে debounceInput... ঠিক আছে?
মিশ্র 3 ডি

@ mix3d এই উত্তরটি বিবেচনা করবেন না। এটি কেবল আমার তদন্ত ছিল আমি প্রশ্নটিতে রাখতে চাইনি। আপনি সম্ভবত সঠিক। গৃহীত উত্তর চেক করুন। এটি সঠিক এবং প্রশ্নের সাথে মেলে আমি এটি সম্পাদনা করেছি।
মার্টিনটাইভার্গা

আমার ভুল ... আমি বুঝতে পারি নি যে আপনি নিজের প্রশ্নের উত্তর দিয়েছেন, হা!

5

আপনার যদি এটির খুব স্বল্পতম পদ্ধতির প্রয়োজন হয় তবে আমি একটি তৈরি করেছিলাম (মূলত আইই সমর্থন করার জন্য ভয়েজস-টিপস থেকে শুরু করে) যা এখানে উপলভ্য: 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>

দ্রষ্টব্য: উপরের উদাহরণে আমি অনুসন্ধানের ইনপুটটির একটি উদাহরণ তৈরি করেছি যা সরবরাহিত কাস্টম বিলম্বের সাথে API কে কল করতে পারেprops


1

যদিও বেশিরভাগ এখানে সমস্ত উত্তর ইতিমধ্যে সঠিক, কেউ যদি দ্রুত সমাধানের সন্ধানে থাকে তবে আমার কাছে এটির জন্য একটি নির্দেশ রয়েছে। https://www.npmjs.com/package/vue-lazy-input

এটি @ ইনপুট এবং ভি-মডেলের ক্ষেত্রে প্রযোজ্য, কাস্টম উপাদান এবং ডিওএম উপাদানগুলিকে সমর্থন করে, ডিবাউন এবং থ্রোটল করে।

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

আপনি যদি ভ্যু ব্যবহার করছেন তবে আপনি এর v.model.lazyপরিবর্তেও ব্যবহার করতে পারেন debounceতবে মনে রাখবেন v.model.lazyসর্বদা কার্যকর হবে না কারণ ভ্যু এটি কাস্টম উপাদানগুলির জন্য সীমাবদ্ধ করে।

কাস্টম উপাদানগুলির জন্য আপনার :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
আপনি কি এই সমাধান সম্পর্কে আরও তথ্য যুক্ত করতে পারেন?
রোচা

2
দয়া করে আরও কিছুটা ব্যাখ্যা করুন। এছাড়াও মনে রাখবেন যে এটি সুপ্রতিষ্ঠিত উত্তরগুলির সাথে একটি পুরানো থ্রেড, সুতরাং কীভাবে সমস্যার সমাধানের জন্য আপনার সমাধানটি আরও উপযুক্ত তা আপনি স্পষ্ট করে বলতে পারেন?
jpnadas

এটি কেন পছন্দের সমাধান এবং এটি কীভাবে কাজ করে তা ব্যাখ্যা করে যদি আপনি কোনও সরবরাহ সরবরাহ করেন তবে এটি আরও সহায়তা করে। আমরা কেবল কোড সরবরাহ না করেই শিক্ষিত করতে চাই।
টিন ম্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.