Solution & What I learn

[JS - Project] 검색어 자동완성 기능 구현하기 | Issue & Solution

heeyeonjeong 2020. 12. 6. 18:07
반응형

ByteDgree 1차 과제로 검색어 자동완성 기능을 구현하는 페이지를 만들고 있다.

배열 처리 / string 자료형 가공 /  Mock API 활용한 비동기 처리를 활용하여 서비스 구현하기

 

 

🔥 Issues

 

1. favicon 오류가 생겼다

 

Failed to load resource: the server responded with a status of 500 (Internal Server Error)

 

❌ 캐시 삭제를 했는데도 react 파비콘이 그대로 남아있었다

❗ 구글링 한 결과, 아래 코드를 HTML에 추가하면 된대서 넣어봄 → error 해결

 

<link rel="icon" href="data:;base64,=">

 

- Chrome이나 FireFox에서는 favicon.ico에 링크가 걸려있지 않으면 서버를 다시 호출하고 404 에러가 발생한다.

이를 막기 위해서 favicon이 없음을 알려줘야 한다. <head></head> 태그사이에 위 코드를 넣어준다.

 

 

2. fetch API 이용해 JSON 데이터 받아오기, 뭐가 문젤까 계속 안된다.. 

 

❌ 하도 안되니까 지금 문제가 저게 맞는지도 의심됨.. 유튜브로 강의 보기

 

❗ 미쳤다 하루 종일 잡고 있다가 해결했다.. 정말 정말 별거 아니고 async, await로 try, catch 써서 출력하면 되는 거였는데 너무 어렵게 생각했다.. 나 진짜 갈길이 멀다.. 그래도 행복하다..

 

//data fetch
async function dataLoad() {
  let searchWord = searchBox.value;
  try {
    await fetch(`http://localhost:3000/autocomplete?keyword=${searchWord}`)
      .then((response) => response.json())
      .then((data) => makeList(data));
  } catch (error) {
    console.log(error);
  }
}

 

 

 

3. innerHTML, innerTEXT, textContent

 

- 문득 저 property들의 차이점이 궁금해져서 찾아봤다.

 

innerHTML vs innerTEXT

 

//innerText
o.innerText="<b>abc</b>";
// <b>abc</b>

//innerHTML
o.innerHTML="<b>abc</b>";
// abc

 

- innerHTML는 태그를 인식하여 내부의 text만 출력하고, innerTEXT는 태그와 text 전체를 문자로 인식한다

 

 

innerTEXT vs textContent

 

//예시
<p>   Hi,   My  name   is   Heeyeon   </p>

//innerText
const desc = document.querySelector('p').innerText;
console.log(desc);

Hi My name is Heeyeon  // 불필요한 공백 제거

//textContent
const desc = document.querySelector('p').textContent;
console.log(desc);

   Hi,   My  name   is   Heeyeon   //공백까지 출력

 

- innerText는 불필요한 공백을 제거 후 출력하고,

- IE의 경우 위와 같이 나타나지만, 현재의 크롬 버전에서는 둘 다 동일하게 결과가 나타난다. 

- textContent가 더 먼저 사용되어 브라우저 호환성도 좀 더 높다. 또한 큰 차이는 아니지만 더 가볍다고 알려져 있다.

 

 

4. 출력된 list 내부의 keyword를 클릭하면 input의 입력값이 해당 keyword로 바뀌기

 

//keyword click시 input value 변경
function valueChange(e) {
  const userChoice = e.target.innerHTML;
  searchBox.value = userChoice;
  dataLoad(searchBox.value);
}

 

- 뭔가 맘에 안 드는 코드.. 근데 돌아가긴 하네..

 

 

// 🔥 제출! Review 내용은 추가 기록 예정


🔥 Review 

 

1. async, await구문과 then은 같이 사용하지 않는다.

 

await fetch(`http://localhost:3000/autocomplete?keyword=${searchWord}`)
  .then((response) => response.json())
  .then((data) => paintList(data));
      
↓
      
const response = await fetch(`http://localhost:3000/autocomplete?keyword=${searchWord}`);
const data = await response.json();
paintList(data);

 

 

 

2. 각각의 리스트 아이템마다 클릭 이벤트 리스너를 붙이기 보다, '이벤트 위임' 개념을 사용하여 조금 더 효율적으로 이벤트 리스너 등록하기

2-1. 리스트 아이템 선택시, 새로운 데이터 로드하지말고 목록을 초기화해보기

 

//list 출력
function paintList(words) {
  completeBox.innerHTML = "";
  for (let i = 0; i < words.length; i++) {
    const completeWord = document.createElement("li");
    completeBox.appendChild(completeWord);
    completeWord.innerHTML = words[i];
    completeWord.addEventListener("click", valueChange);
  }
}

//keyword click시 input value 변경
function valueChange(e) {
  const userChoice = e.target.innerHTML;
  searchBox.value = userChoice;
  loadData(searchBox.value);
}

 

//list 출력
function paintList(words) {
  completeBox.innerHTML = "";
  for (let i = 0; i < words.length; i++) {
    const completeWord = document.createElement("li");
    completeBox.appendChild(completeWord);
    completeWord.innerHTML = words[i];
  }
}

// //keyword click시 input value 변경
function valueChange(e) {
  const userChoice = e.target.innerHTML;
  searchBox.value = userChoice;
  completeBox.innerHTML = "";
}

completeBox.addEventListener("click", valueChange);

 

- for문으로 만들어진 list마다 이벤트를 걸어 뒀는데, 이벤트 위임 개념을 사용하여 for문의 event를 제거하고 list를 감싸는 ul에 event를 걸어 e.target으로 value를 가져왔다.

 

-  검색어 완성 리스트에서 user가 클릭한 단어를 input 창에 뜨게 하는 기능이다. 생각해보니 클릭하는 동시에 리스트를 비워야하는데 그에 맞는 검색어를 다시 load하여 데이터를 또 받아왔다.  → 'loadData' 함수를 제거하고 'completeBox'를 비웠다.