[Vue3실강] 1강 data, methods, computed, watch

youngseo·2022년 6월 6일
0
post-thumbnail

영화검색 예제

  • data, computed, watch

1. 영화예제 검색 기본 코드

<template>
  <input v-model="title" />
  <button @click="searchMovies">
    Search!
  </button>
  <ul>
    <li
      v-for="movie in movies"
      :key="movie.ImdbID">
      <img
        :src="movie.Poster"
        alt=""
        height="40" />

      {{ movie.Title }}
    </li>
  </ul>
  <button
    //movie.length가 있는 경우 버튼이 화면에 출력
    v-if="movies.length"
    @click="searchMoviesMore">
    More...
  </button>
</template>
<script>
export default {
  data() {
    return {
      title:'',
      page:1,
      movies:[]
    }
  },
  methods: {
    async searchMovies() {
      this.page=1
      let res=await fetch(`https://www.omdbapi.com?apikey=7035c60c&s=${this.title}&page=${this.page}`)
      res = await res.json()
      const { Search, totalResults } = res
      this.movies = Search
      this.page=2
    },
    async searchMoviesMore() {
      let res = await fetch(`https://www.omdbapi.com?apikey=7035c60c&s=${this.title}&page=${this.page}`)
      res = await res.json()
      const { Search, totalResults } = res
      this.movies.push(...Search)
      this.page += 1
    }
  }
}
</script>

2. 중복되는 코드 합치기

  methods: {
    async searchMovies() {
      console.log(isFirst)
      if(isFirst) {
        //밑에서 push로 밀어넣기 위해서 빈배열로 초기화
        this.movies = []
        this.page=1
      }
      let res=await fetch(`https://www.omdbapi.com?apikey=7035c60c&s=${this.title}&page=${this.page}`)
      res = await res.json()
      const { Search, totalResults } = res
      this.movies.push(...Search)
      this.page += 1
    }

클릭이 일어났을 때 클릭 이벤트를 인수로 넣어주기 때문에 isFirst는 무조건 truthy가 되게 됩니다.

따라서 click버튼을 실행하는 경우 바로 searchMovies함수가 실행되도록 다음과 같이 작성을 힐 스 있습니다.

  <input v-model="title" />
  //실행을 시킴
  <button @click="searchMovies()">
    Search!
  </button>

즉, vue.js에서는 함수의 이름만 연결을 해도 되지만 어떤 인수를 받아 메소드를 실행시키는 경우에는 ()를 통해 받을 인수를 설정해줄 수 있습니다.

따라서 아래와 같이 Search버튼 클릭시 실행시킬 searchMovies함수에는 true를 인수로 넣어줍니다.

<template>
  <input v-model="title" />
  <button @click="searchMovies(true)">
    Search!
  </button>
  <ul>
    <li
      v-for="movie in movies"
      :key="movie.ImdbID">
      <img
        :src="movie.Poster"
        alt=""
        height="40" />

      {{ movie.Title }}
    </li>
  </ul>
  <button
    v-if="movies.length"
    @click="searchMovies()">
    More...
  </button>
</template>

이렇게 작성을 해주면 한 함수를 사용하면서도 만약 다른 타이틀 값을 검색하는 경우 초기화가 되게 실행을 할 수 있습니다.

3. enter입력시 검색

v-on이벤트에 enter수식언을 붙여 작성하면 됩니다.

  <input
    v-model="title"
    @keydown.enter="searchMovies(true)" />

디렉티브
-v-model, v-for, v-bind, v-if 등

4. computed속성을 이용한 필요한 데이터 정리

computed속성을 이용해 위의 res.data 중 필요한 데이터만 뽑아내어 사용할 이름을 설정해보도록 하겠습니다.


앞서, 클래스를 다시 상기시켜보도록 하겠습니다.

class Name {
  constructor(first, last) {
    this.first = first
    this.last = last
  }
  fullName() {
    return `${this.first} ${this.last}`
  }
}

위와 같이 정의된 함수에서 fullName을 얻기 위해서는 아래와 같이 호출을 했어야했습니다.

const n = new Name('Heropy', 'Park')
console.log(n.fullName())

하지만 fullName메소드 앞에 get을 붙이는 경우 함수처럼 호출하지 않아도 사용을 할 수 있었습니다.

class Name {
  constructor(first, last) {
    this.first = first
    this.last = last
  }
  get fullName() {return `${this.first} ${this.last}`
  }
}

const n = new Name('Heropy', 'Park')
console.log(n.fullName)

즉, 사용을 할 때는 데이터처럼 사용을 하지만 실제로 fullName은 함수이었습니다.


이와 유사하게 computed에 정의된 메소드도 get이라는 키워드를 붙이지 않을 뿐이지 내부에서는 getter와 동일하게 작동을 합니다.

즉, 값을 얻는 용도의 함수지만 데이터처럼 사용이 됩니다.

  computed: {
    //Getter
    customMovies(){
      //this.movies를 통해 원본 데이터를 가져옵니다(⭐원본데이터는 필수입니다)
      return this.movies.map(movie => {
        return {
      //사용할 데이터를 뽑아 원하는 이름으로 정의를 해줍니다.    
          poster: movie.Poster,
          title: movie.Title,
          id: movie.imdbID
        }
      })
    }
  },  

이렇게 계산한 데이터는 아래와 같이 사용할 수 있습니다.

  <ul>
    <li
      v-for="movie in customMovies"
      :key="movie.id">
      <img
        :src="movie.poster"
        alt=""
        height="40" />

      {{ movie.title }}
    </li>
  </ul>

computed속성의 캐싱

보관법을 통해 methode를 사용할 때는 ()를 통해 호출해줘야합니다.

<template>
  <h2>{{ msg }}</h2>
  <h2>{{ reverseMsg() }}</h2>
  <h2>{{ reverseMsg() }}</h2>
  <h2>{{ reverseMsg() }}</h2>
  <h3>{{ reversedMsg }}</h3>
  <h3>{{ reversedMsg }}</h3>
  <h3>{{ reversedMsg }}</h3>
</template>
<script>
export default {
  data() {
    return {
      msg: 'HEROPY?!'
    }
  },
  computed: {
    reversedMsg() {
      return this.msg.split('').reverse().join('')
    }
  },  
  methods: {
      reverseMsg() {
        return this.msg.split('').reverse().join('')
      }
  },
}
</script>

computed와 method의 반복사용의 차이

  • computed로 만든 데이터의 경우 캐싱이 되기 때문에 여러번 재사용을 하더라도 캐싱된 데이터를 통해 바로 화면에 출력이 됩니다. 즉, 계산은 1번만 하게 됩니다.

  • 하지만, method의 경우 사용할 때마다 호출이 되게 됩니다. 즉 계산이 호출하는 횟수만큼 하게 됩니다.

  • 따라서 출력되는 데이터는 똑같더라도 반복 사용되는 경우 computed를 사용하면 조금 더 효율적입니다.

computed속성의 setter

computed속성의 setter(값을 지정할 때 실행되는 함수)를 사용할 수도 있습니다.setter의 경우 vuex를 사용할 때 효율적으로 사용할 수 있습니다.

  <h2>{{ msg }}</h2>
  <h3>{{ reversedMsg }}</h3>
  <button @click="reversedMsg=123456">
    Set!!
  </button>
reversedMsg: {
  get() { //Getter
    return this.msg.split('').reverse().join('')
  }, 
    set(newvalue) { //Setter
      console.log('computed Setter', newvalue)
    }
}

computed속성과 watch속성

data, computed 등 반응형 데이터를 감시하는 용도로 사용되는 속성이 바로 watch입니다.

  watch: {
    movies(newValue, oldValue) {
      console.log('new', newValue)
      console.log('old', oldValue)
    }

영화를 검색하게 되면, 아래와 같이 확인을 할 수 있습니다.

이렇게 watch속성을 이용해 어떠한 데이터가 바뀌면 처리를 하는 로직을 작성할 수 있습니다.

0개의 댓글