Как создать приложение для отслеживания прогноза погоды
Рассказываем, как с помощью Vue 3 и Vite создать простое приложение, которое показывает прогноз погоды.
Введение
Привет! Меня зовут Анна Блок, я автор одноименного YouTube-канала о программировании. Представьте, что вы — веб-разработчик и хотите пополнить портфолио новыми работами. Самое лучше решение — попробовать написать то, что будет охватывать несколько технологий.
В инструкции покажу, как сделать простое приложение для прогноза погоды. Так мы сможем отработать несколько технологий: HTML, CSS, JavaScript, Vue, Vite и подключение API. После — задеплоить проект на облачный сервер Selectel.
Начало работы с Vite
В качестве инструмента сборки будем использовать Vite. С его помощью легко запустим любой JavaScript-фреймворк.
Первым шагом установим Vite. Создаем папку на компьютере, которая будет сохранять данные проекта, и переносим ее в редактор кода VS Code. Далее открываем терминал и вводим код, чтобы создать проект из шаблона:
npm create vite@latest
Теперь добавим в проект необходимые пакеты. Для этого нужно дать согласие системе — пишем «y» и нажимаем Enter.
В ответ получаем конфигурационные файлы и строку Project name. В ней указываем имя будущего проекта. У меня — weather, но можно назвать по-другому. Нажимаем Enter, чтобы продолжить установку.
Далее выбираем необходимый фреймворк и язык программирования. В нашем случае — Vue и JavaScript.
После — вводим в терминал три команды, чтобы начать работу над проектом:
cd weather
npm install
npm run dev
В результате получаем ссылку localhost. Переходим по ней и видим стандартную страницу:
Верстка приложения
На странице Vite и Vue нужно убрать все лишнее, заполнить ее разметкой и стилями будущего проекта. Это поможет понять, как он будет выглядеть и с какими элементами нам придется работать.
Сейчас проект состоит из следующих файлов и папок:
Обратите внимание на папку src — именно с ней мы будем работать. При этом все изменения данных будут отражаться в браузере в момент разработки.
Внутри src есть две папки — assets и components. Поскольку мы делаем простое приложение, предлагаю удалить последнюю папку и ее содержимое. На реальных проектах этого делать не рекомендую, но в нашем случае она ни на что не повлияет.
В assets удаляем лишнее изображение формата svg. Саму папку не трогаем.
Далее открываем файл App.vue, в котором отражены ошибки. Они появились из-за того, что мы удалили папку components. Нам внутреннее содержимое файла не потребуется, поэтому просто удалим его. В результате файл должен быть пустым.
Теперь переходим к созданию разметки. Указываем основные теги <template>
, внутрь добавляем <div>
с классом weather и ниже размещаем <script>
:
<template>
<div class="weather"></div>
</template>
<script>
</script>
В <div>
добавляем класс с контейнером, чтобы разместить поисковую строку, кнопку и информацию о погоде. Ниже — класс weather-bg для хранения изображений.
<template>
<div class="weather">
<div class="container">
<div class="card weather-form">
<input type="text" class="weather-form__input" placeholder="Enter city">
<button class="weather-form__btn">Search</button>
</div>
<div class="weather-info">
<div class="weather-info__text">
<p class="card">Phuket</p>
<p class="card">30°C</p>
<p class="card">Sunny</p>
</div>
</div>
</div>
<div class="weather-bg">
<div>
<img class="weather-bg__img bg" src="./assets/bg.jpg" alt="App Background">
<img class="weather-bg__img overcast" src="./assets/overcast.jpg" alt="App Background">
<img class="weather-bg__img partly-cloudy" src="./assets/partly-cloudy.jpg" alt="Partly Cloudy">
<img class="weather-bg__img sunny" src="./assets/sunny.jpg" alt="Sunny">
</div>
</div>
</div>
</template>
Заранее сохраняем картинку, которая будет отображаться при загрузке приложения. Для остальных описываем разные состояния погоды. За основу возьмем overcats (пасмурно), partly cloudy (переменная облачность) и sunny (солнечно). Подходящие фоны можно найти на любом сервисе стоковых изображений.
Все изображения переносим в папку assets. В файл style.css добавляем основные стили. Подключаем шрифт, прописываем переменные и указываем стандартные сбросы.
@import url('https://fonts.googleapis.com/css2?family=Karla:ital,wght@0,200..800;1,200..800&display=swap');
:root {
--font: "Karla", sans-serif;
--accent: #12C0DD;
--accent-rgb: 18, 192, 221;
--light: #FFFFFF;
--border-radius: 10px;
--width-line: 2px;
--tr: .3s;
}
* {
margin: 0;
padding: 0;
}
body, html {
height: 100vh;
}
body {
font-family: var(--font);
height: 100%;
}
input, button {
font-family: var(--font);
}
#app {
height: 100%;
}
Далее стилизуем блок с контентом. Центрируем его посередине экрана, указываем возможность изменения фона и прописываем функцию добавления классов, чтобы они могли меняться в зависимости от типа погоды.
Основные стили:
.weather {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.weather-bg {
position: absolute;
left: 0;
right: 0;
top: 0;
margin: 0 auto;
width: 100%;
height: 100%;
z-index: -1;
}
.weather-bg > div {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
Основные стили для изображений:
.weather-bg__img {
width: 100%;
height: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
object-fit: cover;
opacity: 0;
transition: var(--tr) ease-in-out;
}
Стиль для основного фона:
.weather .weather-bg__img.bg {
opacity: 1;
}
Стиль для разных типов погоды. Для примера рассмотрим солнечную (sunny), но вы можете установить несколько вариантов и подобрать несколько состояний — вместо sunny нужно будет записать другие варианты:
.weather.sunny .weather-bg__img:not(.sunny) {
opacity: 0;
}
.weather.sunny .weather-bg__img.sunny {
opacity: 1;
}
.container {
width: 100%;
max-width: 1000px;
margin: 0 auto;
padding-left: 15px;
padding-right: 15px;
display: grid;
grid-template-columns: 1fr 100px 200px;
gap: 20px;
box-sizing: border-box;
}
.card {
background-color: var(--light);
border-radius: var(--border-radius);
padding: 20px 30px;
box-sizing: border-box;
}
.weather-form {
display: flex;
align-items: stretch;
gap: 20px;
}
.weather-form__input {
flex-grow: 1;
font-size: 20px;
border: var(--width-line) solid rgba(var(--accent-rgb), .3);
border-radius: var(--border-radius);
padding: 10px 15px;
box-sizing: border-box;
transition: var(--tr);
}
.weather-form__input:focus {
outline: none;
border-color: var(--accent);
}
.weather-form__btn {
flex-basis: 180px;
font-size: 20px;
background-color: rgba(var(--accent-rgb), .3);
border: none;
border-radius: var(--border-radius);
padding: 10px 15px;
box-sizing: border-box;
cursor: pointer;
transition: var(--tr);
}
.weather-form__btn:hover {
background-color: var(--accent);
}
.weather-form,
.weather-load,
.weather-info {
grid-column: 1 / 4;
}
.weather-load {
display: flex;
align-items: center;
height: 87px;
}
.weather-info__text {
display: grid;
grid-template-columns: 1fr auto auto;
gap: 20px;
font-size: 40px;
}
Подготовка фреймворка Vue
Ранее мы запустили инструмент сборки Vite. Вся структура приложения уже подготовлена за нас. Осталось внести изменения в разметку и дописать скрипты.
Информацию о погоде будем получать из реальных источников. Для этого воспользуемся любым бесплатным API. В нашем случае — Weather API.
Переходим на сайт и авторизируемся, чтобы получить ключ для работы с API. Открываем файл App.vue. Нас интересует блок <script>...</script>
.
<script>
export default {
data() {
return {
};
},
computed: {
weatherClass() {
}
},
methods: {
weatherSearch() {
},
resetSearchQuery() {
}
}
};
</script>
В нем прописываем основную структуру кода.
- В
data
будем управлять полученными данными. - В
computed
пропишем изменения фона приложений, в зависимости от типа погоды. - В
methods
подключим API и изменения в работе приложения.
Чтобы передавать приложению погодные характеристики из API, нужно открыть доступ к изменению данных. Для этого используем интерполяцию. В <div>
указываем названия необходимых значений, а в <script>
добавляем функцию, которая возвращает их в объект данных, data()
.
<div class="weather-info__text">
<p class="card">{{ location }}</p>
<p class="card">{{ temperature }}°C</p>
<p class="card">{{ description }}</p>
</div>
data() {
return {
location: '',
temperature: 0,
description: '',
};
}
Указываем в элементах интерфейса input и button связь функций. В директиву v-model добавляем переменную searchQuery
.
<input type="text" class="weather-form__input" v-model="searchQuery" @keyup.enter="weatherSearch" placeholder="Enter city">
<button class="weather-form__btn" @click="weatherSearch">Search</button>
data() {
return {
location: '',
temperature: 0,
description: '',
searchQuery: '',
};
}
Подключаем API для сбора данных о погоде и добавляем два условия. Сначала необходимо обработать поисковый запрос, затем — сбросить введенную фразу из <input>
.
methods: {
weatherSearch() {
this.loading = true;
this.error = false;
fetch(`https://api.weatherapi.com/v1/current.json?key=69ed7b91ab4b4d4f9f282327242604&q=${this.searchQuery}`)
.then(response => response.json())
.then(data => {
this.loading = false;
this.location = data.location.name;
this.temperature = data.current.temp_c;
this.description = data.current.condition.text;
this.resetSearchQuery();
})
.catch(error => {
this.loading = false;
this.error = true;
console.error(error);
});
},
resetSearchQuery() {
this.searchQuery = '';
}
}
Поскольку в catch указаны значения loading
и error
, их также необходимо добавить в ветку data
(). Это позволит отображать строку загрузки и планировать вывод ошибок на случай, если API перестанет обрабатывать данные через поиск.
data() {
return {
location: '',
temperature: 0,
description: '',
searchQuery: '',
loading: false,
error: false,
};
}
<div class="card weather-load" v-if="loading">...</div>
<div class="weather-info" v-show="!error && location && temperature !== 0 && description">
<div class="card" v-if="error">...</div>
<div class="weather-info__text">
...
</div>
</div>
Для изменения фона добавим :class
в <div>
, куда установлен класс weather.
<div class="weather" :class="weatherClass">
Далее пишем функцию, после которой появятся дополнительные классы напротив <div>
. И это только в том случае, если в {{ description }}
отображается соответствующее описание.
Напомню, что мы описывали только три состояния погоды, но таких значений может быть больше. Не забудьте подготовить фоны для каждого нового состояния.
computed: {
weatherClass() {
if (this.description.includes('Sunny')) {
return 'sunny';
} else if (this.description.includes('Overcast')) {
return 'overcast';
} else if (this.description.includes('Partly cloudy')) {
return 'partly-cloudy';
} else {
return '';
}
}
},
Финальный шаг — создаем приложение:
npm run build
Готово, мы сделали простое приложение по прогнозу погоды с нуля!
Деплой проекта
Сейчас готовый результат не увидит никто, кроме нас. Чтобы это исправить, перенесем его на облачный сервер Selectel.
В файле vite.config.js добавляем строку base: './'
внутри export default defineConfig({ … })
. Это позволит в build проекта отразить верные пути файлов.
Вводим в терминале команду npm run build
, после которой появится папка dist. В ней будут формироваться итоговые данные проекта. Файлы оттуда выгрузим на облачный сервер.
В панели управления нужно создать аккаунт или авторизоваться, если у вас уже есть учетная запись. Внутри выбираем Облачная платформа и нажимаем Создать сервер.
В настройках указываем имя проекта и устанавливаем минимальную конфигурацию. Для работы приложения много мощностей не нужно.
После установки конфигурации спускаемся вниз и нажимаем Создать.
Возвращаемся в панель управления и переходим в консоль созданного сервера. Для входа нужен логин (root) и пароль. Нажимаем ЛКМ по иконке Горячие клавиши и добавляем сгенерированный пароль.
В терминале вводим набор команд, чтобы загружать файлы на облачный сервер по FTP-протоколу.
- Устанавливаем FTP-сервер (vsftpd):
sudo apt update
sudo apt install vsftpd
- Настраиваем доступ. Для этого редактируем файл конфигурации FTP-сервера:
sudo nano /etc/vsftpd.conf
- Проверяем параметры конфигурации. Они должны быть установлены или раскомментированы и иметь указанные значения:
anonymous_enable=NO
local_enable=YES
write_enable=YES
chroot_local_user=YES
- Перезапускаем сервис:
sudo systemctl restart vsftpd
- Открываем порты в файрволе, если необходимо:
sudo ufw allow ftp
- Проверяем статус сервиса:
sudo systemctl status vsftpd
С помощью IP-адреса, имени пользователя и пароля вы можете войти в FTP-клиент, чтобы подключить приложение к FTP-серверу. Остается только перенести туда готовые файлы из папки dist.
Готово! Сайт доступен по адресу 46.148.229.29:
Заключение
В инструкции наглядно показали, как создать простое приложение для мониторинга погоды. Не бойтесь с ним экспериментировать, добавлять новые функции и улучшать дизайн. Это поможет прокачать навыки и пополнить портфолио новыми проектами.
А чтобы снизить затраты на обслуживание приложения, советуем присмотреться к виртуальному серверу линейки Shared Line. Оплата производится только за потребленные мощности — по модели pay-as-you-go.
Автор: Анна Блок, автор YouTube-канала.