vanilla js로 할 일 목록 만들기
vanilla js로 내 위치의 날씨 만들기
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hello World?</title>
<link rel="stylesheet" href="./style/reset.css" />
<link rel="stylesheet" href="./js-assignment-css.css" />
<script defer src="./js-assignment-js.js"></script>
</head>
<body>
<div id="app">
<!-- weather -->
<section id="weather"></section>
<!-- clock -->
<section id="clock"></section>
<!-- greeting -->
<section id="greeting" class="hide">
<form class="login-box">
<div class="input-box">
<input type="text" id="userName" />
<label for="userName">이름을 입력해주세요</label>
</div>
</form>
</section>
<!-- todo -->
<section id="todo">
<form class="todo-box">
<div class="input-box">
<input type="text" id="todoInp" />
<label for="todoInp">할 일을 입력해주세요</label>
</div>
</form>
<ul id="todoList"></ul>
</section>
</div>
</body>
</html>
script
에 defer
속성을 주어, 스크립트의 다운로드와 함께 html
렌더 중지를 하지 않고 렌더가 완료되고 스크립트의 실행을 시켜주었다
위치 기반의 날씨를 렌더링 하려면 두 가지의 문제가 있었다
첫번째 문제는 Web api
의 navigator
(의 geolocation
)를 활용하면 된다
Web api
란 자바스크립트에 내장된 모델은 아니지만, 우리가 현재 자바스크립트를 실행시키는 웹에서 제공되는 api
이다
Navigator
인터페이스는 사용자 에이전트의 상태와 신원 정보를 나타내며, 스크립트로 해당 정보를 질의할 때와 애플리케이션을 특정 활동에 등록할 때 사용합니다.
Navigator
객체는window.navigator
읽기 전용 속성으로 접근할 수 있습니다.
Navigator.geolocation
읽기 전용 속성은 웹에서 장치의 위치를 알아낼 때 사용할 수 있는Geolocation
객체를 반환합니다. 웹 사이트나 웹 앱은 위치정보를 사용해 결과 화면을 맞춤 설정할 수 있습니다.
[출처] MDN(Navigator-Web API)
코드에서 우선 해당브라우저에서 API
를 사용할 수 있는지 분기처리하고, 사용할 수 있다면 open api
를 활용해서 기능을 구현해주도록 한다
또한 open api
데이터를 가져올 때 생길 에러상황도 구현해준다
// weather
const KEY = "cd9fca71fbee843c7a38d104afaf8bf8";
const $sectionWeather = document.getElementById("weather");
const getWeather = async ({ latitude, longitude }) => {
try {
const res = await fetch(
`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${KEY}&units=metric`
);
const json = await res.json();
const { weather, main } = json;
const $div = document.createElement("div");
$div.classList.add("wrap-weather");
const $span = document.createElement("span");
const $img = document.createElement("img");
$span.textContent = main.temp + "°C";
$img.src = `http://openweathermap.org/img/wn/${weather[0].icon}@2x.png`;
$div.appendChild($img);
$div.appendChild($span);
$sectionWeather.appendChild($div);
} catch (error) {
const $div = document.createElement("div");
$div.classList.add("wrap-weather");
const $span = document.createElement("span");
$span.textContent = "fail to load weahter";
$div.appendChild($span);
$sectionWeather.appendChild($div);
}
};
if ("geolocation" in navigator) {
console.log("위치정보 사용 가능");
navigator.geolocation.getCurrentPosition((position) => {
const { latitude, longitude } = position.coords;
getWeather({ latitude, longitude });
});
} else {
console.log("위치정보 사용 불가능");
}
openweathermap API KEY
는 현재inactivate
해놓았습니다
투두리스트의 경우엔, form
으로 사용자의 입력값을 받아서 todos
라는 배열에 투두를 푸쉬하고, 해당 배열을 렌더링해주는 방식으로 구현했다
입력을 마치고 배열에 투두가 잘 들어갔다면, 입력창을 초기화하고 포커싱을 떼주는 기능까지 구현했다
삭제의 경우, 투두에다가 id
를 삽입해두었다가 해당 id
를 기준으로 배열에서 filter
해주는 방식을 사용했다
삭제가 된 todos라는 배열을 다시 렌더링 해주면 삭제기능은 끝이다
form
의 경우 default
로 행동하는 새로고침을 막기위해 이벤트의preventDefault
를 활용했다
// todo
const $todoList = document.getElementById("todoList");
const $todoForm = document.querySelector(".todo-box");
let todos = [];
$todoForm.addEventListener("submit", (e) => {
e.preventDefault();
const todo = e.target[0].value;
if (!todo) return;
todos.push({
id: todos.length,
desc: todo,
});
renderTodos();
e.target[0].value = "";
document.getElementById("todoInp").blur();
});
function renderTodos() {
$todoList.innerHTML = "";
todos.forEach((todo) => {
const $li = document.createElement("li");
const $inp = document.createElement("input");
const $span = document.createElement("span");
const $btn = document.createElement("button");
$li.id = todo.id;
$li.classList.add("todo");
$inp.name = todo.id;
$inp.id = todo.id;
$inp.type = "checkbox";
$span.textContent = todo.desc;
$span.htmlFor = todo.id;
$btn.classList.add("delete");
$btn.textContent = "삭제";
$li.appendChild($inp);
$li.appendChild($span);
$li.appendChild($btn);
$btn.addEventListener("click", (e) => {
deleteTodo(e.target.parentNode.id);
});
$todoList.appendChild($li);
});
}
function deleteTodo(id) {
todos = todos.filter((todo) => todo.id != id);
renderTodos();
}
본 후기는 유데미-스나이퍼팩토리 10주 완성 프로젝트캠프 학습 일지 후기로 작성 되었습니다.