От автора: в этом уроке мы создадим своего конкурента YouTube под названием VueTube. Делать это будем с помощью Webpack, Vue JS и Flexbox. Скриншот конечного продукта!
Предварительные условия
Vue – замечательный JS front end фреймворк для создания потрясающих интерфейсов. Webpack – упаковщик модулей для JS, который получает файлы, используемые в разработке, и упаковывает их в один статичный файл. Намучались с позиционированием в CSS? Flexbox все упрощает.
Эти техники и инструменты мы будем использовать для создания нашего клона YouTube.
Начало
В этом уроке мы будем создавать и запускать однофайловые компоненты с помощью Webpack. Для начала проверьте, установлен ли у вас vue-cli.
1 |
npm i -g vue-cli |
После установки vue-cli создаем новый проект с помощью билд-шаблона Webpack, который идет вместе с Vue CLI. Запустите в командной строке следующее:
1 |
vue init webpack vuetube |
Ответьте на все вопросы. Нам не понадобится vue-router для этого проекта.
Создание компонента Video Player
Мы создали проект. Теперь можно создать компонент Video Player. Откройте проект в редакторе кода (я рекомендую VS Code). Перейдите в папку /src/components/ и создайте файл VideoPlayer.vue. Отредактируйте компонент:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<template> <div class="video-player"> Welcome to VueTube </div> </template> <script> export default { name: 'VideoPlayer', data () { return { } } } </script> <style scoped> </style> |
Это голый однофайловый компонент Vue. Он включает шаблон для представления, скрипт для логики компонента и стили, которые через scoped ограничены нашим компонентом.
Теперь можно сказать App.vue, чтобы тот показал VideoPlayer вместо компонента по умолчанию HelloWorld. Для этого нам необходимо заменить файл App.vue в /src на этот файл.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<template> <div id="app"> <VideoPlayer/> </div> </template> <script> import VideoPlayer from './components/VideoPlayer' export default { name: 'App', components: { VideoPlayer } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #2c3e50; } </style> |
Мы импортируем правильный компонент и показываем его при старте приложения. Давайте запустим приложение и посмотрим наш прогресс. Запустите:
1 |
cd vuetube && npm run dev |
Создание наших данных
Мы создали приложение, теперь давайте наполним его видео. Для хранения информации о видео будем использовать объект данных Vue. Создадим переменную videos внутри тега script.
1 2 3 4 5 6 |
//VideoPlayer.vue <script> let videos = []; export default { ... |
Мы создали пустой массив videos. Добавим в него 5 видео. Я возьму видео с Tech Reviewer MKBHD. Вы можете использовать любые другие ролики.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
//VideoPlayer.vue let videos = [ { id: 1, title: "18-core iMac Pro Review: Not a Trap!", thumbnail: "//i.ytimg.com/vi/jn9mHzXJIV0/hqdefault.jpg?sqp=-oaymwEZCNACELwBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLAvJvk4k_UNB9nst4pFP-txM1TLZA", youtubeURL: "//www.youtube.com/embed/jn9mHzXJIV0", creator: "Marques Brownlee", likes: 0, views: 0 }, { id: 2, title: "Dope Tech: Camera Robots!", thumbnail: "//i.ytimg.com/vi/UIwdCN4dV6w/hqdefault.jpg?sqp=-oaymwEZCNACELwBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLDhlan32jHSvicGZezDFPjAOdXGUA", youtubeURL: "//www.youtube.com/embed/UIwdCN4dV6w", creator: "Marques Brownlee", likes: 0, views: 0 }, { id: 3, title: "Let's Talk About Tesla Roadster 2020!", thumbnail: "//i.ytimg.com/vi/ctx4YBEdOxo/hqdefault.jpg?sqp=-oaymwEZCNACELwBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLBDnlrC2rVwXamNkicEEbc3Mf4T0w", youtubeURL: "//www.youtube.com/embed/ctx4YBEdOxo", creator: "Marques Brownlee", likes: 0, views: 0 }, { id: 4, title: "Talking Tech with Neil deGrasse Tyson!", thumbnail: "//i.ytimg.com/vi/pqQrL1K0Z5g/hqdefault.jpg?sqp=-oaymwEZCNACELwBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLA5hTiwkz4Tr1w1hSMhPlwtmQeyYw", youtubeURL: "//www.youtube.com/embed/pqQrL1K0Z5g", creator: "Marques Brownlee", likes: 0, views: 0 }, { id: 5, title: "The Apple Ecosystem: Explained!", thumbnail: "//i.ytimg.com/vi/KB4_WIPE7vo/hqdefault.jpg?sqp=-oaymwEZCNACELwBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLCCxXm7aoPShOwON74nhMlGYMUkHw", youtubeURL: "//www.youtube.com/embed/KB4_WIPE7vo", creator: "Marques Brownlee", likes: 0, views: 0 } ]; |
Мы храним 6 основных атрибутов. Для каждого видео Id, Title, URL, Creator, Likes и Views. У нас есть данные, теперь можно вывести их на экран. Первым делом установим переменную videos в объект данных.
1 2 3 4 5 6 7 8 |
export default { name: 'VideoPlayer', data () { return { videos } } } |
Перебор данных в цикле
Отлично, теперь можно перебрать в цикле данные показать список видео в плеере. Для этого воспользуемся директивой v-for.
1 2 3 4 5 6 7 8 9 10 11 12 |
<div class="video-list"> <div :key="video.id" v-for="video in videos" class="thumbnail"> <div class="thumbnail-img"> <img :src="video.thumbnail" /> </div> <div class="thumbnail-info"> <h3>{{video.title}}</h3> <p>{{video.creator}}</p> <p class="thumbnail-views">{{video.views}} Views</p> </div> </div> </div> |
Мы перебираем в цикле созданный ранее массив videos. Запись v-for=”video in videos” перебирает в цикле все объекты или video внутри массива videos.
Мы перебираем массив, поэтому мы можем обращаться к полям из каждого объекта. В списке видео нам необходимо показывать превью, создателя, просмотры и заголовок. Обратиться к этим полям внутри шаблона можно через handlebar нотацию типа {{video.title}}
Превью должно показывать изображение, поэтому нам необходимо привязать поле к src изображения. Для тегов нельзя использовать нотации handlebar. Вместо этого чтобы привязать url, используем :src.
Обновите браузер и посмотрите, что получилось! Должно быть что-то вроде этого:
Приукрашиваем список видео
Отлично! У нас теперь есть список видео. Давайте отформатируем его. Наш список видео должен походить на правый сайдбар с видео на YouTube. Используем в макете Flexbox, чтобы сделать наш список похожим на YouTube.
Во-первых, превью изображение и div с информацией должны быть на одной строке. Для этого добавим в класс превью всего одну строку.
1 2 3 4 5 |
<style scoped> .thumbnail{ display:flex; } </style> |
Отлично, информация и видео расположены на одной строке. Теперь добавим остальные стили.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
.thumbnail img{ width:168px; } .thumbnail-info{ margin-left:20px; } .thumbnail h3{ font-size:16px; } h3, p{ margin:0; padding:0; } .thumbnail-views{ font-size:14px; } |
Обновите браузер!
Настройка активного видео
Мы полностью настроили список превью и можем перейти к отображению наших видео. При первой загрузке приложения можно показывать первое видео из массива. Для этого создадим поле activeVideo в объекте data. С помощью этого поля мы будем показывать видео, которое выбрал пользователь. Чтобы после загрузки страницы устанавливалось первое видео, необходимо установить activeVideo в videos[0].
1 2 3 4 5 6 7 8 9 |
export default { name: 'VideoPlayer', data () { return { videos, activeVideo: videos[0] } } } |
Активное видео стало частью объекта data. То есть мы можем обратиться к нему просто через ссылку this.activeVideo внутри шаблона. Чтобы показать видео с YouTube, можно создать iframe, привязанный к полю youtubeURL нашего объекта video.
1 2 3 |
<div class="video-container"> <iframe width="640" height="360" :src="this.activeVideo.youtubeURL" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe> </div> |
Добавим под iframe остальную информацию о видео.
1 2 3 4 5 6 |
<iframe ....> <h3>{{this.activeVideo.title}}</h3> <div class="row"> <p>{{this.activeVideo.views}} views</p> <p>{{this.activeVideo.likes}} <button>Like</button></p> </div> |
Отлично! Теперь у нас есть активное отображаемое видео. Добавим ему красоты.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
.video-player{ display:flex; width:1200px; margin:auto; } .video-container{ margin-right:40px; } .row{ display:flex; justify-content:space-between; } button{ background:#D0021B; color:white; border:none; padding:10px 20px; } |
Обновите браузер!
Заставляем работать!
Давайте реализуем выбор видео для просмотра. Напишем метод в теге script.
1 2 3 4 5 6 7 8 |
methods:{ chooseVideo(video){ //SET VIDEO AS ACTIVE VIDEO this.activeVideo = video; //INCREASE THE VIDEOS VIEWS BY 1 video.views += 1; } } |
Мы создали метод chooseVideo, который принимает видео в качестве параметра. Этот метод будет вызываться, когда пользователь выбирает превью из списка видео. После выбора видео устанавливаем activeVideo значение видео, по которому был совершен клик, и увеличиваем просмотры на 1.
Созданный метод необходимо привязать к событию click для каждого видео в цикле v-for
1 |
<div @click="chooseVideo(video)" :key="video.id" v-for="video in videos" class="thumbnail"> |
Попробуйте кликнуть на видео в списке! Если все будет хорошо, вы сможете посмотреть выбранное видео.
Настройка кнопки like
Последний наш шаг – настроить кнопку like. Напишем еще один метод, который будет добавлять единицу к общему числу по клику на кнопку.
1 2 3 |
addLike(){ this.activeVideo.likes += 1; } |
Метод addLike можно привязать к кнопку like в шаблоне
1 |
<button @click="addLike">Like</button> |
Обновите браузер и попробуйте лайкнуть видео! Счетчик должен увеличиваться. Значение будет сохраняться даже при переходе к другому ролику.
Добавляем последние штрихи
Напоследок можно добавить логотип нового видео плеера. Сохраните изображение ниже как logo.png в папку assests.
Теперь можно добавить логотип в файл App.vue
1 2 3 4 |
<div id="app"> <img style="width:140px; margin:14px;" src="./assets/logo.png"/> <VideoPlayer/> </div> |
Спасибо, что дочитали до конца. Надеюсь, вам понравился урок. Задавайте вопросы и оставляйте комментарии.
Автор: Alex Brown
Источник: //medium.com/
Редакция: Команда webformyself.