🪁react/react 실습

js 검색기능(3)

하얀성 2023. 12. 27. 11:50

index.html에서 검색 키워드 단어에 따른 데이터(사진, 글)을 출력할 공간생성.

 <div id="search-result-view"></div>

 

model

storeage(데이터 저장 객체), main, Store 등

 

main.js에 아래와 같이 검색 결과를 나타낼 생성자 생성. 

searchResultView: new SearchResultView(),

 

 


view: 받아온 데이터를 출력하는 생성자.

export default class SearchResultView extends View {
  constructor() {
    super(qs('#search-result-view'))

    this.template = new Template();
  }

  show (data = []) {
    this.element.innerHTML =
      data.length > 0
        ? this.template.getList(data)
        : this.template.getEmptyMessage();
    super.show();  
  }
}

class Template {
  getEmptyMessage(){
    return `
      <div class="empty-box">검색결과가 없습니다.</div>
    `
  }
  getList(data = []){
    return `
      <ul class="result">
        ${data.map(this._getItem).join("")}
      </ul>
    `
  }

  _getItem({imageUrl, name}) {
    return `
      <li>
        <img src="${imageUrl}" alt="${name}">
        <p>${name}</p>
      </li>
    `
  }
 
}

 

생성자용 js 파일 만들어서 그 안에 실재로 출력할 Templete 생성자를 만들어줌.

Templete 생성자는 데이터(검색 keyword)를 주면그 데이터에 따라 storeage.js에서  파일을 들고오는 역할.

 

view에 관한 데이터를 연결해주는 전반적인 부분들은 mvc 패턴에서의 controller 부분에서 맡게된다.

 


cotroller 부분: 생성자와 데이터를 연결 및 검색 등을 담당

 

controller은 Store객체를 저장한 store변수, 생성자를 저장한 두개의 변수를 데려와서 초기화.

export default class Controller {
  constructor(store, { searchFormView,searchResultView }) {
    console.log(tag, "constructor");

    this.store = store;

    this.searchFormView = searchFormView;
    this.searchResultView = searchResultView;

    this.subscribeViewEvents();
  }

 


 

초기화 시켜준 메서드들을 통해서 작업.

 

searchKeyword는 .on을 통해 keyword를 데려왔고 거기서 search  함수를 실행하도록 해주었으며,

 

이 controller의 search 함수가 store.search()를 통해 검색기능을 수행하도록 함.(store.search함수는 store 정의 함수이다. 이걸로 storage 안을 검색해서 controller의 search()함수가 제공해준 keyword에 맞는 데이터를 데려옴.)

 

그렇게 render()를 실행하게됨

render함수는 keyword가 있으면 searchResultView에서 정의한 show함수를 통해서 앞서 controller search()로 검색하여 Store의 result변수에 저장해둔 결과값이 출력되거나 혹은 출력자체가 안되도록 막음.

 
subscribeViewEvents() {
    this.searchFormView
      .on("@submit", (event) => this.search(event.detail.value))
      .on("@reset", () => this.reset());
  }

  search(searchKeyword) {
    console.log(tag, "search", searchKeyword);
    this.store.search(searchKeyword)
    this.render()
  }

  reset() {
    console.log(tag, "reset");
  }

  render() {
    if(this.store.searchKeyword.length > 0) {
      this.searchResultView.show(this.store.searchResult)
      return
    }

    this.searchResultView.hide()
  }

 

 

Store.js

const tag = "[Store]";

export default class Store {
  constructor(storage) {
    console.log(tag, "constructor");

    if (!storage) throw "no storage";

    this.storage = storage;

    this.searchKeyword ="";
    this.searchResult = [];
  }

  search(keyword) {
    this.searchKeyword = keyword
    this.searchResult = this.storage.productData.filter(product =>
      product.name.includes(keyword)
      );
  }
}