npm install -g @vue/cli
vue create 프로젝트이름
npm run serve

vue-cli 설치, 프로젝트 생성, 런 서버

 

 

npm i axios
npm i lodash

axios, lodash를 사용하기 위해 다운받는다.

 

 

 

Google Cloud console

 

console.cloud.google.com

youtube data api 키를 발급받는다.

 

 

 

 

컴포넌트 구성은 이와 같다.

App - SearchBar, VideoDetail, VideoList(VideoListItem)

 

<template>
  <div id="app">
    <h1>TUBE</h1>
    <SearchBar/>
    <VideoDetail/>
    <VideoList/>
  </div>
</template>

<script>
import SearchBar from '@/components/SearchBar'
import VideoList from '@/components/VideoList'
import VideoDetail from '@/components/VideoDetail'
export default {
  name: 'App',
  components: {
    SearchBar,    
    VideoList,
    VideoDetail
  }
}
</script>

App.vue

 

App의 하위 컴포넌트를 불러와서 등록, 사용했다.

 

 

<template>
  <div>
    <input type="text" v-model="search">
    <button @click="searchVideo">검색</button>
  </div>
</template>

<script>
import axios from 'axios'
const API_KEY = process.env.VUE_APP_YOUTUBE_API_KEY
export default {
    name: 'SearchBar',
    data:function(){
        return{
            search : null,
        }
    },
    methods : {
        searchVideo(){
            console.log('hello')
            axios({
                method:'get',
                url:'https://www.googleapis.com/youtube/v3/search',
                params : {
                    part : 'snippet',
                    type : 'video',
                    q : this.search,
                    key : API_KEY
                }
            })
            .then((response)=>{
                this.$emit('search-video',response.data.items)
                this.search=''
            })
        }
    }
};
</script>

<style>
</style>

SearchBar.vue

input, button태그가 있다. input 입력값은 v-model으로 데이터 연결을 해준다. (v-model="search")

버튼을 클릭하면 searchVideo라는 메서드를 실행하도록 했다.

searchVideo메서드에서 axios를 이용해서 api 데이터를 불러오려고 한다.

 

 

const API_KEY = process.env.VUE_APP_YOUTUBE_API_KEY

.env.local 이라는 파일에 api key를 변수에 담아두었다.

이것을 이용하기 위해 process.env.변수명 으로 가져왔다.

 

 

 

            axios({
                method:'get',
                url:'https://www.googleapis.com/youtube/v3/search',
                params : {
                    part : 'snippet',
                    type : 'video',
                    q : this.search,
                    key : API_KEY
                }
            })

이렇게 파라미터들은 params에 담아서 url, method와 함께 가져올 수 있다.

 

 

            axios({
                method:'get',
                url:`https://www.googleapis.com/youtube/v3/search?key=${API_KEY}&part=snippet&type=video&q=${this.search}`,
            })

한번에 url에 백틱``과 ${}변수를 이용할 수도 있다.

 

 

 

.then((response)=>{
                this.$emit('search-video',response.data.items)
                this.search=''
            })

axios로 데이터를 가져오면 response.data.items를 emit해준다.

emit이름은 search-video로 했다. emit했기 때문에 SearchBar.vue의 부모컴포넌트인 App.vue에서 받을 수 있게 된다.

 

 

 

    <SearchBar @search-video = "search"/>

App.vue

search-video(emit)을 받아오면 search 메서드를 실행한다.

 

export default {
  name: 'App',
  components: {
    SearchBar,    
    VideoList,
    VideoDetail
  },
  data : function(){
    return{
      videolist : [],
    }
  },
  methods : {
    search(videolist){
      this.videolist = videolist
    },
  }
}

search메서드는 emit할때 보내주었던 response.data.items를 인자로 받는다.

videolist라는 data를 만들고 저장해주었다.

 

 

    <VideoList :videolist="videolist"/>

이 데이터를 VideoList에 보내준다.

 

 

 

<template>
  <ul>
    <VideoListItem
      v-for="(video, index) in videolist"
      :key="index"
      :video="video"
    />
  </ul>
</template>

<script>
import VideoListItem from "@/components/VideoListItem";
export default {
  name: "VideoList",
  components: {
    VideoListItem,
  },
  props: {
    videolist: Object,
  },
};
</script>

VideoList.vue

VideoListItem을 하위컴포넌트로 가지고 있기 때문에 불러오고 등록하고 사용한다.

App에서 받아온 VideoList를 props에 등록한다. 

이는 Object이기 때문에 v-for으로 요소 하나씩 가져오도록 한다.

요소를 하나씩 video라고 하고, video라는 파라미터를 통해 자식 요소에게 보내준다.

 

 

<template>
<div @click = "select">
    <img :src="video.snippet.thumbnails.high.url" alt="">
    <p>{{video.snippet.title}}</p>
</div>
</template>

<script>
export default {
    name : "VideoListItem",
    props : {
        video : Object
    },
    methods : {
    select : function(){
        this.$emit('select',this.video)
    }
  }
}
</script>

VideoListItem.vue

VideoList에서 받아온 video를 props에 등록한다.

제목을 보여주기 위해 video.snippet.title을 {{}}에 감싸 출력하고, 썸네일을 img 태그에 넣어준다.

리스트 아이템 요소를 클릭하면 동영상을 보여주도록 하기 위해 @click="select"로 클릭하면 select 메서드가 실행되도록 했다. 이 메서드는 this.video 비디오 요소를 emit해준다.

emit 이름은 select이다.

 

 

 

<template>
  <ul>
    <VideoListItem
      v-for="(video, index) in videolist"
      :key="index"
      @select="select"
      :video="video"
    />
  </ul>
</template>

<script>
import VideoListItem from "@/components/VideoListItem";
export default {
  name: "VideoList",
  components: {
    VideoListItem,
  },
  props: {
    videolist: Object,
  },
  methods : {
    select : function(video){
        this.$emit('select',video)
    }
  }
};
</script>

VideoList.vue

@select = "select"

emit으로 select를 인식하면 select메서드를 실행한다. 이 메서드는 select emit을 보내고, 받아온 데이터를 그대로 video라는 이름으로 보내게 된다.

 

 

 

<template>
  <div id="app">
    <h1>TUBE</h1>
    <SearchBar @search-video = "search"/>
    <VideoDetail :video = "video" />
    <VideoList @select = "select" :videolist="videolist"/>
  </div>
</template>
    
<script>
import SearchBar from '@/components/SearchBar'
import VideoList from '@/components/VideoList'
import VideoDetail from '@/components/VideoDetail'
export default {
  name: 'App',
  components: {
    SearchBar,    
    VideoList,
    VideoDetail
  },
  data : function(){
    return{
      videolist : [],
      video : '',
    }
  },
  methods : {
    search(videolist){
      this.videolist = videolist
    },
    select(video){
      this.video = video
    }
  }
}
</script>

App.vue

select emit을 받아오면 select 메서드를 실행한다.

video라는 변수를 만들어서 받아온 video 데이터를 저장한다.

이 video 변수를 VideoDetail에 보내주기 위해 video라는 이름의 파라미터를 이용한다. :video="video" 

 

 

 

<template>
  <div>
    <iframe id="player" type="text/html" width="640" height="360"
  :src="`http://www.youtube.com/embed/${video.id.videoId}`"></iframe>
  </div>
</template>

<script>
export default {
    name : "VideoDetail",
    props : {
    video : Object,
     },
}
</script>

<style>

</style>

VideoDetail.vue

받아온 video 파라미터에 담긴 데이터를 props에 등록한다.

이를 이용해서 iframe 태그에 넣어주면 동영상이 보인다.