ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ


๋‹ค์Œ๊ณผ ๊ฐ™์ด Input ํƒœ๊ทธ์— ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๊ด€๋ จ ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด์„œ ์ถ”์ฒœ ๊ฒ€์ƒ‰์–ด๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ๋„๋ก ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•œ๋‹ค.

 

debounce๋ฅผ ํ†ตํ•œ request ํ˜ธ์ถœ ์ตœ์†Œํ™”

์‚ฌ์šฉ์ž Input ํƒœ๊ทธ์— ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ถ”์ฒœ ๊ฒ€์ƒ‰ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋„๋ก, debounce ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜์—ฌ ์˜๋„์ ์œผ๋กœ ์ง€์ •๋œ ์‹œ๊ฐ„๋งŒํผ ๋”œ๋ ˆ์ดํ•˜์˜€๋‹ค.

let dispatchEvent = debounce(
            (targetText) => { //์‚ฌ์šฉ์ž๊ฐ€ Input ํƒœ๊ทธ์— ์ž…๋ ฅํ•œ value ๊ฐ’
            requestAdapter.get(this.requestUrl, targetText)
                .then((result) => {
                this.displayWordList(
                    this.searchListElement,
                    result
                );
            })
            }
            ,this.DEFAULT_DELAY_TIME);

์ด๋•Œ debounce ํ•จ์ˆ˜์—์„œ ์ฒซ ๋ฒˆ์งธ ์ธ์ž์ธ ์ฝœ๋ฐฑํ•จ์ˆ˜๋Š” targetText ๋ผ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํ˜„์žฌ Input ํƒœ๊ทธ์— ๋‚จ๊ธด ํ‚ค์›Œ๋“œ๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ณ  ์žˆ๋‹ค.

targetText๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ด ๋ฐ›์€ dispatchEvent ๋‚ด์—์„œ argument๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•œ๋‹ค.

(์ฒจ์–ธํ•˜์ž๋ฉด ์ƒ์œ„ ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์ธ callback๊ณผ delayTime์€ ํด๋กœ์ €์— ์˜ํ•ด ์ค‘์ฒฉ_์ž์‹ ํ•จ์ˆ˜ ๋‚ด์—์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค)

 

export const debounce = (callback, delayTime) => {
    let timeout = null;
    return (...args) => { 
        const context = this;
        if(timeout) clearTimeout(timeout);
        timeout = setTimeout(() => callback.apply(context, args), delayTime);
    }
}

์ด๋•Œ ์ „๋‹ฌ ๋ฐ›์€ argument๋Š” Rest ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ†ตํ•ด ๋ฐ›์Œ์œผ๋กœ์จ ๋ฐฐ์—ด์˜ ํ˜•ํƒœ๋ฅผ ๋„๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ๋ฐฐ์—ด ๋‚ด์˜ ์ธ์ž๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ

func.call()์ด ์•„๋‹Œ func.apply()๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

call() ๋ฉ”์„œ๋“œ๋Š” ์ฃผ์–ด์ง„ this ๊ฐ’ ๋ฐ ๊ฐ๊ฐ ์ „๋‹ฌ๋œ ์ธ์ˆ˜์™€ ํ•จ๊ป˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. 
์ด ํ•จ์ˆ˜ ๊ตฌ๋ฌธ์€ ์ธ์ˆ˜ ๋ชฉ๋ก์„, ๋ฐ˜๋ฉด์— apply()๋Š” ์ธ์ˆ˜ ๋ฐฐ์—ด์„ ๋ฐ›๋Š”๋‹ค๋Š” ์ ์ด ์ค‘์š”ํ•œ ์ฐจ์ด์ ์ž…๋‹ˆ๋‹ค.

์ •๋ฆฌํ•˜์ž๋ฉด, Input ํƒœ๊ทธ์—์„œ ์ „๋‹ฌ ๋ฐ›์€ value๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜ธ์ถœ ์ˆœ์„œ๋กœ ์ „๋‹ฌ์ด ๋œ๋‹ค.

์ด๋ฒคํŠธ ๋ฐœ์ƒ => dispatchEvent(value) => debounce Callback(value) => setTimeout Callback(value) => request(value)

debounce์—์„œ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด Promise ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ด ๋ฐ›๋Š”๋‹ค.

export class RequestMockAdapter {
    constructor() {}

    get(url, param) {
        return new Promise((resolve, reject) => {
            resolve(
                param ?
                request.data.filter((item) => item.text.toLocaleLowerCase().indexOf(param.toLocaleLowerCase()) > -1) :
                []
            );
        })
    }
}

์ž…๋ ฅ๋ฐ›์€ ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ(param๊ฐ’) ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ๋‚ด์—์„œ ํ•ด๋‹น ํ‚ค์›Œ๋“œ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ๋‹จ์–ด๋“ค์„ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์— ์ ์žฌํ•˜์˜€๋‹ค.

 

๋งŒ์•ฝ์— K๋ฅผ Input์— ์ž…๋ ฅ์„ ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด K๋กœ ์‹œ์ž‘๋˜๋Š” ๋ชจ๋“  ํ‚ค์›Œ๋“œ๋“ค์„ ์ฐพ๊ณ , Ke๋ฅผ Input์— ์ž…๋ ฅ์„ ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด Ke๋กœ ์‹œ์ž‘๋˜๋Š”

๋ชจ๋“  ํ‚ค์›Œ๋“œ๋“ค์„ ์ฐพ๋Š”๋‹ค. ์ด๋•Œ K๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ธ๋ฑ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ K ๋‹ค์Œ์— ์—ฐ์†๋˜์„œ ์˜ค๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ์—๋Š” K์˜ ์ธ๋ฑ์Šค ์š”์†Œ

(์ตœ์†Œ 0์˜ ๊ฐ’์„ ์ง€๋‹˜)๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ ์—ฐ์†๋˜์„œ ์˜ค๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ์—๋Š” -1์„ ๋ฐ˜ํ™˜ํ™˜๋‹ค.

 

์ด๋•Œ ํ‚ค์›Œ๋“œ์˜ ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ ์ง“์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ toLocaleLowerCase()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฐพ์•„์•ผ ํ•  ํ‚ค์›Œ๋“œ๋ฅผ ์†Œ๋ฌธ์ž๋กœ ํ†ต์ผํ•˜์˜€๋‹ค.

 

filter() ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๊ฐ’์€ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์— ํ• ๋‹น๋˜๋Š”๋ฐ, ์ด๋Š” resolve()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ ํ›„์† ์ฒ˜๋ฆฌ ๋ฉ”์„œ๋“œ์ธ then()์˜ ์ธ์ž์ธ result์—

ํ• ๋‹นํ•˜์˜€๋‹ค.

requestAdapter.get(this.requestUrl, targetText)
                .then((result) => {
                this.displayWordList(
                    this.searchListElement,
                    result
                );
            })

 

focusEvent

๋งˆ์šฐ์Šค๊ฐ€ Input ์ฐฝ์—์„œ ํฌ์ปค์Šค ์•„์›ƒ์ด ๋˜๋ฉด ์ถ”์ฒœ ํ‚ค์›Œ๋“œ ๋ฆฌ์ŠคํŠธ ์ฐฝ์„ ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง€๋„๋ก ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ ์ž ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ์ด์šฉํ•˜์˜€๋‹ค.

document.querySelector('body').addEventListener('click', e => {
             if(!e.target.classList.contains(`${this.textinputElement.getAttribute('class')}`)) {
                 this.searchListElement.style.display = 'none';
             }
        })

ํ•˜์ง€๋งŒ ์ด๋ณด๋‹ค๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์š”์†Œ์—์„œ ํฌ์ปค์Šค๊ฐ€ ๋–จ์–ด์กŒ์„ ๋•Œ๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ์ด๋ฒคํŠธ์ธ focusout/focusin ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์˜€๊ณ  ์ด๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์šฉํ•˜์˜€๋‹ค.

focusout ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒ ์š”์†Œ๋Š” ์žƒ๊ฒŒ ์ดˆ์ ์„ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค.
๋ฐ˜๋ฉด์— focusin ์ด๋ฒคํŠธ๋Š” ์š”์†Œ๊ฐ€ ํฌ์ปค์Šค๋ฅผ ๋ฐ›์„๋ ค๊ณ  ํ•  ๊ฒฝ์šฐ ๋ฐœ์ƒํ•œ๋‹ค.
this.textinputElement.addEventListener('focusout', () => {
            if(listOver) return;
            this.hiddenElem(this.searchListElement); //๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆจ๊ธฐ๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ
        })
        
 this.textinputElement.addEventListener('focusin', e => {
            dispatchEvent(e.target.value); //Input ํƒœ๊ทธ์— ์žˆ๋Š” ํ‚ค์›Œ๋“œ์— ๋”ฐ๋ฅธ ์ถ”์ฒœ ๊ฒ€์ƒ‰ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœ
        })

 

mouseEvent

๋ฆฌ์ŠคํŠธ์— ๋งˆ์šฐ์Šค๊ฐ€ hover๊ฐ€ ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ํฌ์ปค์Šค๋ฅผ ์žƒ๋”๋ผ๋„ ๋ฆฌ์ŠคํŠธ๊ฐ€ ํ™”๋ฉด ์ƒ์—์„œ ์‚ฌ๋ผ์ง€๋ฉด ์•ˆ๋˜๊ธฐ ๋•Œ๋ฌธ์— mouseover/mouseout ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

 this.searchListElement.addEventListener('mouseover', () => {
            listOver = true; //listOver๊ฐ€ ์ฐธ์ผ ๊ฒฝ์šฐ์—๋Š” ๋ฆฌ์ŠคํŠธ๋ฅผ ์‚ฌ๋ผ์ง€์ง€ ์•Š๊ฒŒ return 
        })

        this.searchListElement.addEventListener('mouseout', () => {
            listOver = false;
        })

 

๋Œ“๊ธ€
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
TAG
more
ยซ   2024/10   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
๊ธ€ ๋ณด๊ด€ํ•จ