跳至主要内容

3 篇文章 含有標籤「版本控制」

檢視所有標籤

事件物件屬性 e.target 與 e.currentTarget 的差異與應用 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

前言

在網頁開發中,事件處理是前端工程師必須熟悉的基礎知識之一。當我們使用 JavaScript 或框架(如 Vue、React)監聽 DOM 事件時,瀏覽器會提供一個事件物件(event object)給監聽函式,透過它我們能取得觸發事件的相關資訊。而在事件物件中,最常被初學者混淆的兩個屬性就是 e.targete.currentTarget

這兩者的差別看似微小,但實際上與事件冒泡機制息息相關。如果理解不清,會導致點擊判斷錯誤、事件綁定邏輯混亂,甚至出現無法預期的行為。本文將從概念、重點摘要,再到程式碼範例,逐步說明 e.targete.currentTarget 的異同,並介紹實際開發中如何正確使用。


重點摘要

  1. 事件冒泡(Event Bubbling)

    • 當某個元素觸發事件時,事件會從最深層的子元素向外層父元素依序傳遞。
    • 這意味著外層元素的事件監聽器也可能被觸發。
  2. e.target

    • 代表「事件最初發生的元素」。
    • 使用者實際點擊或操作的 DOM 元素,不論事件是否冒泡到其他父層。
  3. e.currentTarget

    • 代表「當前正在處理事件的元素」。
    • 永遠指向事件監聽器綁定的元素。
  4. 差異核心

    • e.target = 使用者操作的來源元素。
    • e.currentTarget = 當前呼叫事件處理函式的元素。
  5. 常見用途

    • e.target:用於判斷使用者點擊了哪個子元素,常用於事件代理(event delegation)。
    • e.currentTarget:用於保證取得事件綁定的元素本身,避免因冒泡導致判斷錯誤。

範例一:基本點擊事件

以下是一個簡單的 HTML 結構:

<div id="outer" style="padding:20px; background:lightgray;">
Outer Div
<button id="inner">Click Me</button>
</div>

<script>
const outer = document.getElementById('outer');

outer.addEventListener('click', (e) => {
console.log('target:', e.target.id);
console.log('currentTarget:', e.currentTarget.id);
});
</script>

執行結果

  1. 點擊按鈕(id="inner"):

    • e.target.idinner
    • e.currentTarget.idouter
  2. 點擊外層灰色區塊(id="outer"):

    • e.target.idouter
    • e.currentTarget.idouter

說明

  • 使用者實際點擊按鈕,所以 e.targetinner
  • 但因為事件冒泡,outer 的監聽器被觸發,因此 e.currentTarget 永遠是 outer
  • 這正好展示了兩者的不同:一個描述事件來源,一個描述處理者。

範例二:事件代理(Event Delegation)

事件代理是一種常見技巧,將監聽器掛在父層元素,由它統一處理子元素的事件。這種情境下,e.target 就非常重要。

<ul id="list">
<li data-id="1">Item 1</li>
<li data-id="2">Item 2</li>
<li data-id="3">Item 3</li>
</ul>

<script>
const list = document.getElementById('list');

list.addEventListener('click', (e) => {
console.log('target tag:', e.target.tagName);
console.log('currentTarget tag:', e.currentTarget.tagName);

if (e.target.tagName === 'LI') {
console.log('You clicked item with data-id:', e.target.dataset.id);
}
});
</script>

執行結果

  • 點擊 Item 2 時:

    • e.target.tagNameLI
    • e.currentTarget.tagNameUL
    • 印出 "You clicked item with data-id: 2"

說明

  • list(UL)負責監聽整個清單,這就是 e.currentTarget
  • 實際點擊的 <li> 元素才是 e.target
  • 藉由 e.target,我們能知道使用者點的是哪個清單項目,而不用對每個 <li> 綁定監聽器。

範例三:模擬 Vue 的 .self 行為

在 Vue 中有一個 .self 修飾符,代表「只有點擊元素本身,而不是子元素時,事件才觸發」。這其實就是透過 e.target === e.currentTarget 判斷。

<div id="modal" style="width:300px; height:200px; background:rgba(0,0,0,0.5);">
<div style="width:100px; height:100px; background:white; margin:50px auto;"></div>
</div>

<script>
const modal = document.getElementById('modal');

modal.addEventListener('click', (e) => {
if (e.target === e.currentTarget) {
console.log('Clicked on modal background, close modal');
} else {
console.log('Clicked on inner content, do nothing');
}
});
</script>

說明

  • 點擊外層灰色背景時:e.target === e.currentTarget → 成立 → 關閉彈窗。
  • 點擊白色內層時:e.target 為內層 div,而 e.currentTarget 為外層 → 不相等 → 不關閉。

這個邏輯就是框架中 .self 修飾符的實作原理。


總結

  • e.targete.currentTarget 都是事件物件的重要屬性。
  • e.target 表示事件來源,是使用者實際操作的元素。
  • e.currentTarget 表示事件處理者,是目前綁定監聽器的元素。
  • 理解這兩者的差別,對於處理事件冒泡、事件代理、以及控制複雜 UI 行為都至關重要。

當我們需要知道「使用者點了哪個子元素」時,請使用 e.target。當我們需要確保「正在處理事件的元素本身」時,請使用 e.currentTarget

掌握這個觀念,能讓我們在撰寫事件監聽邏輯時更精準,避免誤判來源,也能設計出更乾淨與可維護的程式碼。

Git 指令學習筆記 | 學習筆記

· 閱讀時間約 6 分鐘
kdchang

Git 是現代軟體開發中最常使用的分散式版本控制系統,它幫助開發者管理源代碼的版本和協作。這篇教學將從基礎開始,介紹 Git 的常用命令並提供實際範例,幫助你熟悉如何使用 Git 來進行版本控制與協作。

1. 初始化 Git 倉庫 (git init)

在專案資料夾中使用 git init 可以初始化一個新的 Git 倉庫,這樣就可以開始使用 Git 來管理專案中的檔案版本。

git init

執行後會在專案資料夾內建立一個 .git 的隱藏資料夾,這表示這個資料夾已經被 Git 所管理。

2. 查看當前狀態 (git status)

在進行版本控制時,使用 git status 可以查看專案的當前狀態。這個命令會顯示哪些檔案已經被修改、哪些檔案尚未加入版本控制。

git status

這會列出所有變更過的檔案(包括已修改、尚未追蹤的檔案等)以及當前分支的狀態。

3. 新增檔案到暫存區 (git add)

修改檔案後,必須先使用 git add 把檔案新增到暫存區,才可以進行提交。使用 git add 可以指定單一檔案或多個檔案,或者一次將所有檔案加入暫存區。

git add filename.txt

或將所有變更加入暫存區:

git add .

4. 提交變更 (git commit)

將檔案從暫存區提交到本地版本庫使用 git commit。每次提交時,需要提供一個簡短的描述,解釋這次提交的內容。

git commit -m "新增使用者登錄功能"

5. 設定 Git 使用者資訊 (git config)

在進行提交之前,必須設定 Git 的使用者名稱和電子郵件。這些資料會與每次提交關聯。

git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

這會把你的名稱和郵箱寫入全域設定,未來每次提交都會使用這些設定。

6. 查看提交歷史 (git log)

使用 git log 可以查看專案的提交歷史。這會顯示每次提交的詳細信息,包括提交哈希值、作者、日期和提交訊息。

git log

如果希望更簡潔的輸出,可以使用 --oneline 參數:

git log --oneline

7. 恢復檔案 (git restore)

如果你修改了一些檔案並且還沒有提交,可以使用 git restore 恢復檔案到上次提交的狀態,撤銷變更。

git restore filename.txt

如果想撤銷暫存區的變更,可以使用:

git restore --staged filename.txt

8. 追蹤檔案變動紀錄 (git blame)

如果你想查看某個檔案每一行是誰在什麼時候修改的,可以使用 git blame

git blame filename.txt

這會顯示每一行的修改者與修改時間,有助於了解程式碼的歷史。

9. 建立分支 (git branch)

在 Git 中,分支讓你能夠並行地進行多個工作。你可以使用 git branch 查看目前所有的分支。

git branch

要創建新的分支:

git branch feature-login

10. 切換分支 (git switch)

要切換到不同的分支,可以使用 git switch。例如,切換到 feature-login 分支:

git switch feature-login

如果你要創建並切換到一個新的分支,可以加上 -c 選項:

git switch -c feature-register

11. 切換提交紀錄或分支 (git checkout)

雖然 git switch 是較新的命令,但仍然可以使用 git checkout 切換分支或還原檔案。要切換到某個分支:

git checkout feature-login

若要還原某個檔案到指定的提交:

git checkout <commit_hash> filename.txt

12. 合併分支 (git merge)

將不同分支的更改合併回主分支可以使用 git merge。首先切換到目標分支(例如 main),然後執行合併操作:

git switch main
git merge feature-login

如果有衝突,Git 會提示你解決衝突。

13. 重新整理提交歷史 (git rebase)

git rebase 用來重新整理提交歷史,將一個分支的更改重新應用到另一個分支上,使歷史更為線性。

git switch feature-login
git rebase main

這會將 feature-login 分支的變更,重新應用到 main 分支的最新提交上。

14. 重置提交 (git reset)

如果你想取消最近一次的提交,可以使用 git reset。使用 --soft 保留檔案變更,--hard 則會刪除變更:

git reset --soft HEAD^

這會將上一個提交撤回,但保留檔案變更;若使用 --hard,則會完全撤回提交及變更。

15. 查看操作紀錄 (git reflog)

git reflog 可以幫助你查看 HEAD 的操作紀錄,即便你進行了 resetcheckout 等操作。

git reflog

這個命令列出所有曾經指向 HEAD 的 commit 參考,並且可以用來恢復丟失的提交。

16. 暫存變更 (git stash)

如果你正在進行某些變更,但又需要切換到其他分支處理緊急問題,可以使用 git stash 暫時儲存未提交的變更:

git stash

這會暫時保存變更,並恢復工作目錄到最後一次提交的狀態。待你完成緊急工作後,可以使用 git stash pop 恢復變更。

17. 選擇性地應用提交 (git cherry-pick)

git cherry-pick 讓你可以選擇性地將某個提交應用到當前分支。例如,將 feature-login 分支的某個提交應用到 main 分支:

git cherry-pick <commit_hash>

這對於選擇性地將某些特定變更移動到其他分支非常有用。

18. 子模組 (git submodule)

當專案中有其他專案作為依賴時,可以使用 Git 子模組來管理。首先,將子模組加入專案:

git submodule add <repository_url> path/to/submodule

這會在專案中加入一個指向其他 Git 倉庫的子模組。在克隆專案時,記得加上 --recurse-submodules 來獲取子模組的內容。


總結

以上介紹了 Git 中一些常用的命令,這些命令幾乎涵蓋了日常開發中的大部分需求。熟練掌握 Git 讓你在開發過程中更加高效,無論是單人開發還是團隊協作,都能大大提高工作流的順暢性。如果你還有進一步的需求或疑問,隨時可以深入學習 Git 的進階技巧。

Git 入門教學筆記:從零開始學版本控制 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

為什麼要學 Git?

在軟體開發中,版本控制是一個不可或缺的工具。Git 是目前最流行的版本控制系統,它能幫助你:

  • 記錄每次修改的歷史紀錄
  • 回復到任一個過去的狀態
  • 多人協作開發不衝突
  • 管理分支進行實驗性開發

無論是獨立開發者、團隊協作,還是參與開源專案,Git 都是你的好夥伴。


一、安裝 Git

macOS

brew install git

Ubuntu / Debian

sudo apt update
sudo apt install git

Windows

請至官網下載安裝:https://git-scm.com


二、基本設定

第一次使用 Git 前,請先設定你的名稱與 Email(這會記錄在每次提交的資訊中):

git config --global user.name "你的名字"
git config --global user.email "you@example.com"

你也可以檢查目前的設定:

git config --list

三、建立本地倉庫(repository)

建立一個新資料夾並初始化 Git

mkdir my-project
cd my-project
git init

此時 .git/ 目錄會被建立,代表你已經在這個資料夾啟用了版本控制。


四、版本控制的基本流程

Git 的工作流程大致分為三個區域:

  1. 工作區(Working Directory):你實際修改的檔案
  2. 暫存區(Staging Area):準備提交的檔案
  3. 版本庫(Repository):正式提交的版本歷史

1. 查看狀態

git status

2. 將檔案加入暫存區

git add 檔名
# 或加入全部變動檔案
git add .

3. 提交版本(commit)

git commit -m "加入了首頁 HTML 結構"

五、版本紀錄與回溯

查看提交紀錄

git log

如果想要簡潔查看

git log --oneline

回到先前的狀態(例如最近一次提交)

git checkout HEAD^
# 回到上上一個版本
git checkout HEAD~2

但請注意這樣會進入「detached HEAD」狀態,只是暫時查看,不適合繼續開發。


六、分支操作(branch)

分支是 Git 強大的一環,可以讓你同時開發多個功能而互不干擾。

建立新分支

git branch feature-login

切換分支

git checkout feature-login

或合併成一行:

git checkout -b feature-login

合併分支

切回主分支(通常是 mainmaster):

git checkout main
git merge feature-login

七、遠端倉庫(Remote Repository)

若你使用 GitHub、GitLab 等服務,可以將本地專案推送到遠端:

新增遠端倉庫

git remote add origin https://github.com/yourname/yourproject.git

推送本地分支

git push -u origin main

拉取遠端最新變更

git pull origin main

八、.gitignore 檔案

.gitignore 用來指定不想被 Git 管理的檔案,例如:

node_modules/
.env
*.log
.DS_Store

建立一個 .gitignore 檔案,放進你專案根目錄,就能避免把不該版本控制的東西送到遠端倉庫。


九、常見狀況與解法

修改後不小心沒 add 就 commit 了?

可用下列方式補上:

git add 新增的檔案
git commit --amend

想撤銷修改?

還沒 add 的:

git checkout -- 檔案名

已經 add 了但還沒 commit:

git reset HEAD 檔案名

十、總結:從習慣開始,讓版本控制變簡單

熟悉 Git 的過程一開始可能會覺得繁瑣,但當你習慣了之後,它會成為你每天工作中不可或缺的工具。建議你在小專案中練習基本指令,隨手記錄每次的變更,透過良好的 commit message,讓未來的你感謝現在有好好整理的你。

如果你希望與他人協作開發,Git 更能大幅簡化流程、避免衝突。下一步,你可以學習 Pull Request(PR)、Git Flow、Rebase 等進階技巧,逐步精進你的版本控制能力。

參考文件

  1. Conventional Commits
  2. 約定式提交
  3. [Git] Conventional Commits 規範性提交
  4. git reflog - 還原大招
  5. 為你自己學 Git