IT이야기

Vue2에서 디바운스를 구현하는 방법?

cyworld 2022. 3. 22. 21:24
반응형

Vue2에서 디바운스를 구현하는 방법?

나는 Vue 템플릿에 간단한 입력란을 가지고 있는데, 나는 디바운스를 거의 이와 같이 사용하고 싶다.

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

하지만, 그debounceVue 2에서는 속성이 더 이상 사용되지 않았다.권장 사항에는 "v-on:input + 타사 디바운스 기능 사용"이라고만 나와 있다.

어떻게 그것을 올바르게 구현하는가?

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

그런 다음 필터 키가 나중에 사용됨computed소품

디바운스 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)
}

옵션 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)
  }
}

/구성요소.부에를 하다

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

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

코데펜


옵션 2: 구성 요소 내, 디프 없음

- 한 번 사용하거나 소규모 프로젝트에서 사용할 경우 권장

/구성요소.부에를 하다

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

코데펜

디바인 할당 중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>

하숙 없이 매우 단순함

handleScroll: function() {
  if (this.timeout) 
    clearTimeout(this.timeout); 

  this.timeout = setTimeout(() => {
    // your action
  }, 200); // delay
}

나도 같은 문제가 있었는데 여기 플러그 인 없이 작동하는 솔루션이 있어.

이후<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);
},

만약 당신이 이것에 대해 아주 미니멀한 접근법을 필요로 한다면, 나는 여기서 이용할 수 있는 하나를 만들었다. 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>

이 답변은 수락된 답변보다 먼저 게시한 것에 유의하십시오.그건 옳지 않아.문제의 해결책에서 한 발짝만 앞서 나간 것이다.나는 저자의 구현과 내가 사용한 최종 구현을 보여주기 위해 합격된 질문을 편집했다.


코멘트와 링크된 마이그레이션 문서에 따라 다음 코드를 몇 가지 변경했다.

템플릿:

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

하숙집과 함께 동적 지연을 적용해야 할 경우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를 호출할 수 있는 검색 입력의 예를 만들었는데, API는 다음과 같이 사용자 지정 지연으로 제공된다.props

비록 여기 있는 거의 모든 해답은 이미 정확하지만, 만약 누군가 빠른 해결책을 찾고 있다면, 나는 이것에 대한 지침을 가지고 있다.https://www.npmjs.com/package/vue-lazy-input

@input 및 v-model에 적용되며, 사용자 지정 구성 요소와 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>

디버깅된 메소드를 만들려면 컴퓨터 사용법을 구성 요소의 여러 인스턴스 간에 공유하지 마십시오.

<template>
  <input @input="handleInputDebounced">
<template>

<script>
import debounce from 'lodash.debouce';

export default {
  props: {
    timeout: {
      type: Number,
      default: 200,
    },
  },
  methods: {
    handleInput(event) {
      // input handling logic
    },
  },
  computed: {
    handleInputDebounced() {
      return debounce(this.handleInput, this.timeout);
    },
  },
}
</script>

통제할 수 없는 상태로 작동시킬 수 있다.v-model또한:

<template>
  <input v-model="debouncedModel">
<template>

<script>
import debounce from 'lodash.debouce';

export default {
  props: {
    value: String,
    timeout: {
      type: Number,
      default: 200,
    },
  },
  methods: {
    updateValue(value) {
      this.$emit('input', value);
    },
  },
  computed: {
    updateValueDebounced() {
      return debounce(this.updateValue, this.timeout);
    },
    debouncedModel: {
      get() { return this.value; },
      set(value) { this.updateValueDebounced(value); }
    },
  },
}
</script>

만약 당신이 Vue를 사용하고 있다면 당신은 또한 사용할 수 있다.v.model.lazy대신에debounce하지만 기억해라v.model.lazyVue가 사용자 지정 구성 요소에 대해 제한하므로 항상 작동하지 않음

사용자 지정 구성 요소의 경우:value와 함께@change.native

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

1 화살표 기능을 사용한 짧은 버전(기본 지연 값 포함)

file: debounce.js in ex: (수입 디바운스 '../../utils/proutcounts' )

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

2 믹신 옵션

파일: 디바운스믹신.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 검색 입력 중단

나는 거의 실행하지 않고 디바운드를 사용할 수 있었다.

나는 부스트랩-뷰와 함께 Vue 2.6.14를 사용하고 있다.

이 pkg을 너의 패키지에 추가해라.json: https://www.npmjs.com/package/debounce

이것을 main.js:

import { debounce } from "debounce";
Vue.use(debounce);

내 구성 요소에는 다음과 같은 입력이 있다.

          <b-form-input
            debounce="600"
            @update="search()"
            trim
            id="username"
            v-model="form.userName"
            type="text"
            placeholder="Enter username"
            required
          >
          </b-form-input>

검색() 메서드를 호출하고 검색 메서드는 검색을 수행하기 위해 양식.userName을(를) 사용한다.

디바운스 기능의 실행을 클래스 메서드로 이동할 수 있는 경우, 유틸리티 디코더 lib에서 장식가를 사용할 수 있다(npm install --save utils-decorators):

import {debounce} from 'utils-decorators';

class SomeService {

  @debounce(500)
  getData(params) {
  }
}
 public debChannel = debounce((key) => this.remoteMethodChannelName(key), 200)

부에아제네이터

참조URL: https://stackoverflow.com/questions/42199956/how-to-implement-debounce-in-vue2

반응형