๐Ÿ” ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค FE ๋ฐ๋ธŒ์ฝ”์Šค 5๊ธฐ TIL 231021

Jun 2k (Jun2)ยท2023๋…„ 10์›” 22์ผ
0

๐Ÿ’ป Intro

๋…ธ์…˜ ํด๋กœ๋‹ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•œ์ง€ ์–ด๋А๋ง 5์ผ์ฐจ...
๊ธฐ๋ณธ์ ์ธ ์š”๊ตฌ์‚ฌํ•ญ๋“ค์€ ๊ฑฐ์˜ ๋‹ค ๊ตฌํ˜„ํ–ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๊ธฐ๋Šฅ๋งŒ ๊ตฌํ˜„๋˜์—ˆ์ง€ ์ž์ž˜ํ•œ ์—๋Ÿฌ ํ•ธ๋“ค๋ง๊ณผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง์ด ์กฐ๊ธˆ ๋ฏธํกํ•œ ๋ถ€๋ถ„์ด ์žˆ๋‹ค.
ํ•˜๋‚˜์”ฉ UX๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ๋ณด์™„ํ•ด ๋‚˜๊ฐˆ ์˜ˆ์ •์ด๋‹ค!


๐Ÿง ์˜ค๋Š˜ ์ƒˆ๋กญ๊ฒŒ ๋ฐฐ์šด ๊ฒƒ

์ด๋ฒคํŠธ ๋””๋ฐ”์šด์‹ฑ

์—๋””ํ„ฐ ์ž…๋ ฅ๋˜๋Š” ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ผ์ • ์‹œ๊ฐ„ ์ง€๋‚˜๋ฉด ์ž๋™์œผ๋กœ ์„œ๋ฒ„์— ์ €์žฅํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด์•ผ ํ–ˆ๋‹ค. ์ด๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ๋œ ๊ฒƒ์ด ์ด๋ฒคํŠธ ๋””๋ฐ”์šด์‹ฑ์ด๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ timer๋ฅผ ์ง€์ •ํ•˜๊ณ  timer๋ฅผ ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ setTimeout์œผ๋กœ ํ…€์„ ๋‘์–ด์„œ ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ์ง€์—ฐ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.
๋‚˜๋Š” ๋…ธ์…˜์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌธ์„œ์˜ ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ผ์ • ์‹œ๊ฐ„(๋‚˜๋Š” 2์ดˆ๋กœ ์„ค์ •ํ–ˆ๋‹ค)์ด ์ง€๋‚˜๋ฉด ํ•ด๋‹น ๋‚ด์šฉ์„ ์„œ๋ฒ„์— ์ €์žฅํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

let timer = null;
      // ์ˆ˜์ • ์ด๋ฒคํŠธ ๋ฐœํ–‰์‹œ
      $editHeaderInput.addEventListener('keyup', (e) => {
        // ํƒ€์ด๋จธ ์ดˆ๊ธฐํ™”
        if (timer !== null) clearTimeout(timer);

        const newTitle = e.target.value; // ์ƒˆ๋กœ์šด ์ž…๋ ฅ๊ฐ’

        timer = setTimeout(() => {
          const { selectedDoc } = this.state;
          // ์ €์žฅํ•  ๊ธฐ์กด ์ž„์‹œ ์ €์žฅ ๋‚ด์šฉ์„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
          const editDoc = getStorage('selectedDoc', {
            title: selectedDoc.title,
            content: selectedDoc.content,
          });

          const newDoc = { ...editDoc, title: newTitle };

		  // ์ƒˆ๋กœ์šด ์ž„์‹œ ์ €์žฅ ๋ฌธ์„œ๋ฅผ ์Šคํ† ๋ฆฌ์ง€์— ์ถ”๊ฐ€
          addStorage('selectedDoc', newDoc);
		  // ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด newDoc๋ฅผ App.js๋กœ ๋‚ด๋ณด๋‚ด๊ธฐ
          onEditing(newDoc);
        }, 2000);
      });

์œ„์™€ ๊ฐ™์ด ์ž„์‹œ ์ €์žฅ ๋ฌธ์„œ๋ฅผ ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅํ•˜๊ณ  ์ˆ˜์ •๋œ ์ž„์‹œ ์ €์žฅ ๋ฌธ์„œ์— ๋Œ€ํ•œ ์ƒํƒœ๊ฐ’์„ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋„˜๊ฒจ์ค€๋‹ค.

์‹ค์ œ ๋…ธ์…˜์€ ๋ฌธ์ž๊ฐ€ ์ž…๋ ฅ๋  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„์— ์ €์žฅ์„ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค. ํ•˜์ง€๋งŒ ๋‚˜๋Š” ๋””๋ฐ”์šด์‹ฑ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ 2์ดˆ์˜ ๋”œ๋ ˆ์ด๋ฅผ ์ ์šฉํ•ด๋ณด์•˜๋‹ค. ์‹ค์ œ๋กœ ์„œ๋ฒ„์— ํšจ์œจ์ ์œผ๋กœ ์š”์ฒญ์„ ํ•˜๋Š” ์ž‘์—…์„ ๋‚œ ์•„์ง ํ•˜์ง€ ์•Š์„ ์ƒํƒœ๋ผ ๋””๋ฐ”์šด์‹ฑ์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


focus()

์ด๋ฒคํŠธ ๋””๋ฐ”์šด์‹ฑ์„ ํ†ตํ•ด input์™€ textarea ๋‚ด value ๊ฐ’์„ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๊ณ  state๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ฉด์„œ ์žฌ๋ Œ๋”๋ง์„ ํ•˜๋ฉด์„œ ํ•ด๋‹น ์š”์†Œ์— ๋Œ€ํ•œ ํฌ์ปค์‹ฑ์ด ํ’€๋ฆฌ๋Š” ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.
์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด title์ด๋‚˜ content์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ–ˆ์„ ๋•Œ currentFocus ์ƒํƒœ์˜ element ๊ฐ’์ด ํ•ด๋‹น ์š”์†Œ์™€ ์ผ์น˜ํ•˜๋ฉด focus()๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํฌ์ปค์‹ฑ์„ ์œ ์ง€์‹œ์ผœ์ฃผ๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

// header
const $editHeaderInput = document.querySelector('input#title');
	  // ์ˆ˜์ •ํ•˜๊ณ  ์žˆ๋Š” ํ•ญ๋ชฉ์ด title์ด๋ฉด ์žฌํฌ์ปค์‹ฑ
      if (currentFocus.element === 'title') $editHeaderInput.focus();
      $editHeaderInput.value = title;

// textarea
$editor.value = !content ? '' : `${content}`;
      // ์ˆ˜์ •ํ•˜๊ณ  ์žˆ๋Š” ํ•ญ๋ชฉ์ด content์ด๋ฉด ์žฌํฌ์ปค์‹ฑ
      if (currentFocus.element === 'content') $editor.focus();


๐Ÿ™„ ์•Œ๊ณ  ์žˆ์—ˆ์ง€๋งŒ ๋” ๊ณต๋ถ€ํ•ด์•ผ ํ•  ๊ฒƒ

์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง ์ œ์–ด

๊ฐ™์€ ํŒ€์› ์„์ฃผ๋‹˜๊ณผ ์˜คํ”„๋ผ์ธ ๋ชจ๊ฐ์ฝ”์—์„œ ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง ์ด์Šˆ์— ๋Œ€ํ•ด์„œ ๊ฐ™์ด ๊ณ ๋ฏผ์„ ํ–ˆ์—ˆ๋‹ค. ๊ฐ•์˜์—์„œ ๋ฐฐ์šด ์ด๋ฒคํŠธ ๋ธ๋ฆฌ๊ฒŒ์ด์…˜(delegation)๊ณผ e.stopPropagation() ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ง์ ‘ ์ ์šฉํ•˜๋ ค๋‹ˆ HTML ์š”์†Œ ์–ด๋””์— ํ•ด๋‹น ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง ๋ฐฉ์ง€ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š”์ง€ ํ—ท๊ฐˆ๋ ธ๋‹ค. ์ด๋ฒคํŠธ ๋ธ๋ฆฌ๊ฒŒ์ด์…˜์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฐฉ๋ฒ•๊ณผ ์ด๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•œ HTML ๊ตฌํšํ™” ๋ฐฉ์•ˆ์„ ์ฐพ์•„๋ด์•ผ ๊ฒ ๋‹ค.



๐Ÿ‘€ ๋А๋‚€์ 

๐Ÿ‘ Keep

  • ์˜คํ”„๋ผ์ธ ๋ชจ๊ฐ์ฝ”์—์„œ ํŒ€์›์ธ ์„์ฃผ๋‹˜๊ณผ ๊ฐ™์ด ๊ณ ๋ฏผํ•˜๋ฉด์„œ ์ด์Šˆ์— ๋Œ€ํ•ด์„œ ์ฐพ์•„๋ณด๊ณ  ํ•ด๊ฒฐ๋ฐฉ์•ˆ์„ ๋ชจ์ƒ‰ํ•˜๋‹ค๊ฐ€ ๋ณด๋‹ˆ ๋‚ด๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” ๋ถ€๋ถ„๊ณผ ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•œ ๋ฉ”ํƒ€์ธ์ง€๋ฅผ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.
    ์•ž์œผ๋กœ ์ด์Šˆ์— ๋Œ€ํ•œ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์„ ์ฃผ์ €์—†์ด ๊ณต์œ ํ•ด์•ผ ๊ฒ ๋‹ค.

๐Ÿ˜ฑ Problem

  • ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ๋ถ€์กฑํ•˜๊ณ  ๊ด€๋ จ๋œ ๋ฒ„๊ทธ๋ฅผ ๊ณ„์† ๊ณ ์น˜๊ณ  ์žˆ๋Š” ์ค‘์ด๋‹ค.
    ์•„๋งˆ ๊ธฐ์กด์— HTML ์š”์†Œ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ๋‚˜ ์ด๋ฒคํŠธ๋ฅผ ๋ถ€์—ฌํ•  ๋•Œ ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์„ ๊ณ ๋ คํ•˜์ง€ ์•Š๊ณ  ๋ฌด์ง€์„ฑ์œผ๋กœ ์„ค์ •ํ•ด์„œ ๊ทธ๋Ÿฐ ๊ฒƒ ๊ฐ™๋‹ค.
    ํ•ญ์ƒ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ๋Š” ๋ฒ„๋ธ”๋ง ์ œ์–ด์— ๋Œ€ํ•œ ๋กœ์ง๋„ ํฌํ•จ ์‹œ์ผœ์•ผ ๊ฒ ๋‹ค.

๐Ÿ˜œ Try

  • ์ด๋ฒคํŠธ ๋ธ๋ฆฌ๊ฒŒ์ด์…˜ ํŒจํ„ด ๊ฒ€์ƒ‰ ๋ฐ ๊ตฌํ˜„
  • ์—๋””ํ„ฐ ๋‚ด ๋ฌธ์„œ ์ œ๋ชฉ์ด ์žˆ์„ ๊ฒฝ์šฐ ๋งํฌ๋ฅผ ๋ Œ๋”๋ง ๊ตฌํ˜„
  • ํ•˜์œ„ ๋ฌธ์„œ ๋งํฌ ๋ Œ๋”๋ง ๊ตฌํ˜„
  • textarea ์—๋””ํ„ฐ๋ฅผ contenteditable๋ฅผ ํ™œ์šฉํ•œ ๋ฆฌ์น˜ํ•œ ์—๋””ํ„ฐ๋กœ ๋ณ€๊ฒฝํ•ด๋ณด๊ธฐ


๐Ÿ˜… ํ•ด๋‹น ๋‚ด์šฉ์€ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ํ‹€๋ฆฐ ๋ถ€๋ถ„์ด๋‚˜ ์˜คํ•ดํ•˜๊ณ  ์žˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ํ”ผ๋“œ๋ฐฑ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

profile
ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ค€๋น„์ค‘...

0๊ฐœ์˜ ๋Œ“๊ธ€