iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 3
12
Modern Web

從 Hooks 開始,讓你的網頁 React 起來系列 第 3

[Day 03 - 計數器] 用原生 JavaScript 做一個簡單的計數器

感謝 iT 邦幫忙與博碩文化,本系列文章已出版成書「從 Hooks 開始,讓你的網頁 React 起來」,首刷版稅將全額贊助 iT 邦幫忙鐵人賽,歡迎前往購書,鼓勵筆者撰寫更多優質文章。

昨天我們複習了在 React 中一定會用到的 JavaScript 語法,不知道昨天的內容會不會有點吃不消呢?可以在底下留言告訴我,如果喜歡我們的頻道,不要忘了按讚、分享、訂閱,還要開啟小鈴鐺喔

今天我們先來用原生的 JavaScript 來完成一個簡單的計數器!之後幾天會再把這個計數器改成用 React 來寫,讓你感受一下兩者的差別,體會 React 幫前端工程師解決了什麼樣的痛點。

Imgur

完成一個簡單的計數器畫面

現在我們先來用 CodePen 完成一個簡單計數器的畫面,這個計數器的畫面是由 Oleg Frolov 所設計,並放置於 dribble 上。

Imgur

首先在 HTML 的部分可以複製下面的程式碼,這個部分的內容很簡單,三個 div 區塊分別對應到畫面上的「向上箭頭」、「數字」、「向下箭頭」:

<!-- HTML -->
<div class="container">
  <!-- 向上箭頭 -->
  <div class="chevron chevron-up"></div>
  <!-- 數字 -->
  <div class="number">
    256
  </div>
  <!-- 向下箭頭 -->
  <div class="chevron chevron-down"></div>
</div>

接著在 CSS 的部分可以貼上:

/* CSS */
/**
 * Credit:
 * counter design is from dribbble (https://dribbble.com/shots/5539678-Stepper-VI)
 * chevron icons are from fontAwesome (https://fontawesome.com/icons/chevron-down?style=solid)
**/
html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  background-color: #f26072;
  display: flex;
  align-items: center;
  justify-content: center;
}

.container {
  display: flex;
  align-items: center;
  flex-direction: column;
}

.number {
  font-size: 72px;
  color: #fbf5f5;
  font-family: Verdana;
  line-height: 1.75em;
  text-align: center;
  user-select: none;
}

.chevron {
  background: transparent center center;
  background-repeat: no-repeat;
  cursor: pointer;
  width: 70px;
  height: 70px;
  transition: all 0.3s;
}

.chevron-up {
  background-image: url("data:image/svg+xml, %3Csvg aria-hidden='true' focusable='false' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23f6909c' d='M240.971 130.524l194.343 194.343c9.373 9.373 9.373 24.569 0 33.941l-22.667 22.667c-9.357 9.357-24.522 9.375-33.901.04L224 227.495 69.255 381.516c-9.379 9.335-24.544 9.317-33.901-.04l-22.667-22.667c-9.373-9.373-9.373-24.569 0-33.941L207.03 130.525c9.372-9.373 24.568-9.373 33.941-.001z'%3E%3C/path%3E%3C/svg%3E");
}

.chevron-up:hover {
  background-image: url("data:image/svg+xml, %3Csvg aria-hidden='true' focusable='false' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23fbf5f5' d='M240.971 130.524l194.343 194.343c9.373 9.373 9.373 24.569 0 33.941l-22.667 22.667c-9.357 9.357-24.522 9.375-33.901.04L224 227.495 69.255 381.516c-9.379 9.335-24.544 9.317-33.901-.04l-22.667-22.667c-9.373-9.373-9.373-24.569 0-33.941L207.03 130.525c9.372-9.373 24.568-9.373 33.941-.001z'%3E%3C/path%3E%3C/svg%3E");
}

.chevron-down {
  background-image: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23f6909c' d='M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z'%3E%3C/path%3E%3C/svg%3E");
}

.chevron-down:hover {
  background-image: url("data:image/svg+xml,%3Csvg aria-hidden='true' focusable='false' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23fbf5f5' d='M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z'%3E%3C/path%3E%3C/svg%3E");
}

這時候你應該就可以看到頁面上出現計數器的畫面。如果你想要用一個「完整的頁面」來檢視目前的畫面,可以在 CodePen 右上方點選「Change View」之後按下「Debug mode」:

Imgur

這時會跳出一個獨立的頁面,如果有需要 Debug 的話,使用這個 Deubg 頁面較不會被 CodePen 中的其他元素所干擾,因此也更容易找到元素在網頁中的位置:

Imgur

完成之後按下儲存,這個頁面就會保存在你的 Dashboard 中了。

完成的程式碼和畫面可以看 Day 3 - Counter Started Template @ Codepen。

在這 30 天中主要會著重在 JavaScript 和 React 的應用,所以在 HTML 和 CSS 的部分並不會著墨太多。

讓計數器動起來

現在已經完成了計數器的畫面,接著我們希望當使用者點擊「向上箭頭」的時候數字增加,當使用者點擊「向下箭頭」的時候數字減少,像是這樣的話,可以怎麼做呢?

Imgur

你可以先花 5 ~ 10 分鐘的時間試著嘗試看看能不能做到上圖的效果,這裡提供幾個關鍵字包括 querySelectoraddEventListener。如果嘗試了 10 分鐘還沒做出來的話,也不用氣餒,回憶一下你剛剛試著用什麼方法解決這個問題,然後繼續看一下去可以怎麼做。

因為使用者點擊滑鼠的時候要改變數字,所以勢必要去監聽使用者對於「箭頭」的「點擊事件」,因此:

  1. 先透過 querySelector 去選到「箭頭」的元素(即,upElementdownElement
  2. 使用者「點擊」箭頭後要更新網頁中的數字部分,因此一樣透過 querySelector 去選到「數字」元素(即,numberElement
  3. 透過 addEventListener 監聽使用者的點擊事件(click
  4. 在增加或減少網頁上的數字前,要先知道「當前網頁上的數字」是多少,這裡可以透過 numberElement.textContent 取得,同時這裡因為取得的數字是字串,所以需先透過 Number() 方法,將字串轉成數值,以便進行加減。
  5. 當前網頁上的數值(currentNumber)進行加減後,透過 textContent 給回修改後的數字。
// JavaScript
// STEP 1: 透過 querySelector 選擇到 HTML 中的「箭頭」元素
const upElement = document.querySelector(".chevron-up");
const downElement = document.querySelector(".chevron-down");

// STEP 2: 透過 querySelector 選擇到 HTML 中的「數字」元素
const numberElement = document.querySelector(".number");

// STEP 3: 監聽 click 事件,並執行對應的行為
upElement.addEventListener("click", e => {
  // STEP 4: 取得當前網頁上的數字
  const currentNumber = Number(numberElement.textContent);

  // STEP 5: 將數字增加後帶回網頁上
  numberElement.textContent = currentNumber + 1;
});

downElement.addEventListener("click", e => {
  const currentNumber = Number(numberElement.textContent);
  numberElement.textContent = currentNumber - 1;
});

如此,就可以在使用者點擊按鈕之後讓計數器產生對應的變化:

Imgur

完成之後按下儲存,這個頁面就會保存在你的 Dashboard 中了。完成的程式碼和畫面可以看 Day 3 - Finished Counter @ Codepen。

補充:調整成自己喜歡的 CodePen 設定

透過 CodePen 的設定,可以將程式編輯的畫面調整成自己偏好的樣式。方式是點擊右上角的頭像後,點選「Setting」:

Imgur

這裡面可以進行許多不同的偏好設定,你可以選擇喜歡的佈景主題、字型、字體大小、縮排長度等等:

Imgur

參考資源


上一篇
[Day 02] React 中一定會用到的 JavaScript 語法
下一篇
[Day 04 - 計數器] 把 HTML 寫在 JavaScript 中!? - JSX 的使用
系列文
從 Hooks 開始,讓你的網頁 React 起來30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

1
yumememooo
iT邦新手 5 級 ‧ 2021-04-04 11:04:23

你好,請問一下 background-image: url中的東西是怎麼來的,Dribble有提供嗎?

pjchender iT邦新手 3 級 ‧ 2021-04-09 00:41:52 檢舉

yumememooo 它就是 SVG 喔!SVG 的原始碼是類似 HTML(確切來說是 XML)的程式碼,所以只是直接把 SVG 的原始碼貼到 background-image 的 url 中。

0
milkeddy1
iT邦新手 5 級 ‧ 2021-07-23 00:48:01

你好 剛入門寫程式
想請問為什麼currentNumber寫在最外層function裡面只會抓到256
而不是加減過後的數字
是跟作用域有關嗎

我要留言

立即登入留言