🔍 搜尋結果:使用

🔍 搜尋結果:使用

Git 入門上手教材:第3課 ── 學會 git 版本切換

## 課程目標 - 學會 git 版本切換 ## 課程內容 上次的內容順利提交之後 這次讓我們試試看切換版本功能! 在 git log 內,每個 commit 紀錄後面,會看到一串提交代號,類似這樣 `0e78f9d62d1342f29b1a2a3af8b751f1a4d653ef` git 強大的版本歷史功能,就跟這個相關 請找到前一筆提交的代號,然後輸入切換版本指令 ``` git checkout 148106fcb1a496ab034ad5f6253c1dd8fe21eb22 ``` 看一下資料夾內容,會發現就跟「搭時光機」一樣,整個專案的狀態「回溯」到上一次提交了! 再看一下這時 `git log` 會顯示什麼,會發現歷史紀錄也只剩兩筆了! 你可以再找出更前一筆提交代號 ``` git checkout 0e78f9d62d1342f29b1a2a3af8b751f1a4d653ef ``` 會發現回溯到第一筆提交狀態了!神奇吧! --- 時光機搭完了,要如何回到最新狀態呢? ``` git checkout master ``` 這樣就行了! master 其實是主要的 branch 名稱 先不用管 branch 是什麼意思,之後會提到 在學習 git 過程中,很多東西先「享受用起來的好處」就夠了 背後機制與觀念,有點一知半解沒關係,真的卡關再去鑽研就可以了 反正目的就是管理檔案的歷史版本而已嘛! ## 課後作業 接續前一課的作業,你的專案目前有三個 html 檔案 你突然又有點反悔,覺得原本全部資訊寫在 `index.html` 那樣比較好? 開發專案時,像這樣反反覆覆其實很正常,就切回去看一下,感覺看看有沒有比較好,再決定即可 請使用 `git checkout {版本}` 指令,切回前一個 commit 的版本 你可以看一下資料夾內容,應該會發現變回之前的樣子了! --- 請輸入 `git log`,應該會發現,歷史紀錄也倒退了一個版本! 完成以上任務,你就完成這次的課程目標了! --- 交作業的方法: 可以把整段 `git log` 顯示的文字內容複製,貼到留言區 也可以直接截圖視窗內 `git log` 的內容,上傳到留言區

Git 入門上手教材:第1課 ── 學會 git 初始化

## 課程目標 - 學會 git 初始化 ## 課程內容 這次的課程,主要是透過每課作業練習實務情境 關於 git 的基本安裝,網路上有非常多教學,請根據你的作業系統,自己找一套安裝方法 不論是使用「終端機」讓你輸入指令,或者是有 GUI(圖形化介面)讓你點擊 UI 執行指令,都可以 關於 git 的基本觀念,學起來可深可淺,我只會簡單說明工作上需要的觀念 覺得黑箱或者想深入研究的話,可以上網搜尋相關關鍵字,深入理解 git 底層機制 --- 在要使用 git 追蹤的資料夾內,首先要使用的指令是 ``` git init ``` 這會初始化資料夾環境,讓 git 開始追蹤資料夾內所有檔案變化的一舉一動 其實不用想得太神奇,這指令只是在資料夾內建立一個隱藏的資料夾 `.git/` 而已(你可以根據你的作業系統,想辦法找到這個隱藏的資料夾) 後續的 git 指令,背後都是去查看 `.git/` 的內容而已 --- 初次使用 git,打指令可能會被要求設定名稱信箱,這些要用來記錄在 git 歷史訊息內,辨識操作者 ``` git config --global user.name "您的名稱" git config --global user.email "您的信箱" ``` --- 接著來試用兩個指令 首先是查看目前的工作狀態 ``` git status ``` 因為還沒有任何程式碼,所以應該會顯示「沒東西」的中文或英文訊息 接著來查看歷史編輯紀錄 ``` git log ``` 一樣會顯示「沒紀錄」的中文或英文訊息 這兩個基本指令,對於學習非常有幫助 在每次打任何 git 指令之前與之後,都打打看這兩個指令,可以幫助認識當前追蹤狀況 ## 課後作業 請開一個新資料夾,用 git 初始化這個資料夾 接著分別輸入 `git status` 與 `git log` 應該會看到 git 回應「沒東西」與「沒紀錄」的訊息 完成以上任務,你就完成這次的課程目標了! --- 交作業的方法: 可以把 `git status` 與 `git log` 顯示的文字內容複製,貼到留言區 也可以直接截圖視窗內 `git status` 與 `git log` 的內容,上傳到留言區

HTML新標籤dialog簡化modal實作

看youtube看到的 新的<dialog></dialog>標籤內建開關api 範例: ``` const dialog = document.querySelector("dialog") dialog.show() // 打開dialog(原先位置) dialog.showModal() // 打開dialog(置中且屏蔽背景) dialog.close() // 關閉dialog ``` 幾個重點: 1.不用再用CSS display開關 2.用showModal()自動置中且屏蔽背景 3.modal設定css背景方式: ``` dialog::backdrop { background-color: hsl(250, 100%, 50%, 0.25); } ``` 4.可結合form使用,form提供新的method="dialog",或是form裡面的button設定formmethod="dialog"來關閉 ``` <dialog> <form method="dialog"> <input type="text" /> <button type="submit">Submit</button><!-- 不會submit--> <button formmethod="dialog" type="submit">Cancel</button><!-- 不會submit--> </form> </dialog> ``` 5.如果想要點擊dialog以外的地方自動關閉可用下列程式碼: ``` dialog.addEventListener("click", e => { const dialogDimensions = dialog.getBoundingClientRect() if ( e.clientX < dialogDimensions.left || e.clientX > dialogDimensions.right || e.clientY < dialogDimensions.top || e.clientY > dialogDimensions.bottom ) { dialog.close() } }) ``` 6.dialog.close()方法可以傳值到Dialog.returnValue ``` Dialog.close(valueToPass) const getValue=Dialog.returnValue ``` 參考資料: [Modals Will Never Be The Same - HTML dialog Element](https://blog.webdevsimplified.com/2023-04/html-dialog/) [影片 The New dialog HTML Element Changes Modals Forever ](https://www.youtube.com/watch?v=ywtkJkxJsdg&t=620s)

給OOP初學者的建議:先搞懂「資料跟行為在一起」就好,其它的慢慢來

初學者接觸OOP,幾乎都會有以下疑惑: 我到底為什麼要學OOP?OOP解決了什麼問題?書上這些範例就算不用OOP也寫得出來吧? 然後覺得「繼承」、「多型」、「介面」、「抽象類別」等等的名詞很難,覺得OOP很難。 其實這些名詞雖然重要,但對新手來說,本來就很難在一開始就搞懂。 建議先搞懂「資料跟行為在一起」是什麼,以及它的好處在哪,就可以了,其它的慢慢來。 # 什麼叫做「資料跟行為在一起」? 假設我們在開發一個「中英文互助學習網」,鼓勵中文人士與英語人士登入討論。 這個系統的貼文、留言功能會顯示「發文日期」。 發文日期要根據使用者的註冊身份(台灣人、英語人士)顯示不同格式(台灣格式、西方格式)。 下面就以這個日期格式的功能舉例說明「資料跟行為在一起」是什麼意思。 ## 作法一:直接硬寫(不OOP、資料跟行為混在一起) 初學者通常會用最簡單、也最直覺的作法,直接硬寫出來,像這樣: ``` <?php $postDate = '2016-06-02'; # 假設資料庫取出來的發文日期長這樣 if (/* 判斷是否顯示台灣格式 */) { # 轉換成這樣 2016.6.2 $arr = explode('-', $postDate); $year = $arr[0]; $month = $arr[1]; $day = $arr[2]; echo "$year.$month.$day"; } else { // 西方格式 # 轉換成這樣 6/2/2016 $arr = explode('-', $postDate); $year = $arr[0]; $month = $arr[1]; $day = $arr[2]; echo "$month/$day/$year"; } ``` 這種寫法的資料(日期)跟行為(轉換成各種格式)混在一起。 它的優點是寫起來很簡單,缺點則有兩個: * 日期格式的邏輯會重複出現在很多地方,整段code會到處重複出現 * 整段code大概會塞在 `div` 或是 `span` 的裡面,導致它跟HTML混在一起,很亂 ## 作法二:自訂函數(不OOP、資料跟行為沒混在一起) 為了解決作法一遇到的問題,聰明的初學者很快就想到可以用「自訂函數」!就像這樣: ``` <?php function localFormat($date) { $arr = explode('-', $date); $year = $arr[0]; $month = $arr[1]; $day = $arr[2]; return "$year.$month.$day"; } function englishFormat($date) { $arr = explode('-', $date); $year = $arr[0]; $month = $arr[1]; $day = $arr[2]; return "$month/$day/$year"; } $postDate = '2016-06-02'; # 假設資料庫取出來的發文日期長這樣 if (/* 判斷是否為台灣人身份 */) { echo localFormat($postDate); } else { // 英語人士身份 echo englishFormat($postDate); } ``` 這種寫法將行為(轉換成各種格式)用自訂函數給獨立出來,也大幅改善了作法一遇到的問題。 對小型的網頁程式來說,這招非常好用,不但開發快速、簡單,還漂亮地將資料跟行為拆開。 但是程式規模變大之後,為了將各種行為拆出來,會寫出很多自訂函數,類似這樣: ``` ?php function localFormat($param) { // blah blah ... } function englishFormat($param) { // blah blah ... } function someTask($param) { // blah blah ... } function anotherTask($param) { // blah blah ... } function otherTask($param) { // blah blah ... } //... ``` 於是又衍生出三個問題: 1. 像localFormat、englishFormat這樣的函數名稱意義模糊,看不出是處理日期、人名,還是什麼東西的格式 2. 這些自訂函數各有不同的行為,全部放在一起顯得很亂,應該要想辦法分類、整理這些函數 3. 像localFormat、englishFormat這樣的函數,只吃特定格式的參數,最好能跟某種資料的形式綁在一起,以後要改程式時,能讓相關的資料跟行為一起被看到 問題1很好解決,只要替函數名稱加前綴字變成dateLocalFormat、dateEnglishFormat就行了。 問題2也很好解決,只要多開幾個檔案,把相關的函數放進同一個檔案就行了。 問題3就很棘手,資料跟行為拆開之後,如何在概念上又找方法整理在一起? ## 作法三:使用class(OOP、資料跟行為在一起) 正是這些處理資料、整理行為的問題,導致了OOP的誕生: ``` <?php class Date { public $year; public $month; public $day; public function __construct($date) { $arr = explode('-', $date); $this->year = $arr[0]; $this->month = $arr[1]; $this->day = $arr[2]; } public function localFormat() { return $this->year . '.' .$this->month . '.' . $this->day; } public function englishFormat() { return $this->month . '/' .$this->day . '/' . $this->year; } } $postDate = '2016-06-02'; # 假設資料庫取出來的發文日期長這樣 $date = new Date($postDate); if (/* 判斷是否為台灣人身份 */) { echo $date->localFormat(); } else { // 英語人士身份 echo $date->englishFormat(); } ``` OOP的寫法,一次解決了前述三個問題: 問題1 => 現在從類別名稱就可以知道底下方法的意義了 問題2 => 現在相關的函數都整理進同一個類別底下成為方法了 問題3 => 現在資料的形式都統一在constructor處理一次,之後不管新增多少方法都不用處理資料了 這就是所謂的「資料跟行為在一起」,也正是OOP的核心概念。 利用這種方式整理程式碼、寫出一個又一個的類別,可以大幅提昇程式碼的品質。 # 結論 上述的作法一跟作法二並沒那麼糟糕,但確實會帶來一些問題。 對於小型的網頁程式來說,可能還算夠用。 但是隨著程式規模變大,如果將概念上相關的資料跟行為整理在一起,會很有幫助。 實務上也可以先從作法二開始寫起,直到發現某些資料跟行為關係密切,再拉出來整理成類別即可。 至於很多OOP教學會提到的「繼承」、「多型」、「介面」、「抽象類別」等等名詞,一時搞不懂沒有關係,你可能實務上也暫時用不到。之後找時間慢慢搞懂它們的用途就好。 光是知道「將資料跟行為放在一起」的技巧,就能夠開始寫OOP程式碼了。 (註:本篇文章的程式碼純屬教學用途。實務上PHP已經有DateTime類別可以使用,或是用更漂亮的Carbon類別。) ## Q&A Q1:我常常設計一些類別,只有資料沒有行為,聽起來OK嗎? 不OK,這很不OOP,而且沒意義。 乾脆直接用關聯式陣列去表示那些資料就好。 Q2:我常常設計一些類別,只有行為沒有資料,聽起來OK嗎? 這個要看情況,不一定。 但唯一可以確定的是,這種作法很不OOP。 因為OOP的核心是「資料跟行為在一起」。 這也是為什麼你會看到有人明明寫了類別、用了物件,別人卻說「這不夠OOP」。 然後你又會看到像JavaScript這樣連「類別」關鍵字都沒有(ES5以前),卻能夠寫出很OOP程式碼的關係。 判定的標準都是一樣的,而且也就只有這麼一個標準:資料跟行為有沒有在一起。 Q3:一個類別包含的概念是越大越好,還是越小越好? 不一定。不過我們從作法一到作法三的過程,有一個明確目的:希望讓程式碼更好懂。 如果聲稱一個類別包含的概念很大(例:設計LanguageHelpWebsite類別,用來代表「中英文互助學習網」需要的所有功能),那會把幾乎整個網站的所有行為跟資料都放進去,成為所謂的God object。它可沒有讓程式碼更好懂。 相反地,如果聲稱一個類別包含的概念很小(例:分別設計LocalDate、EnglishDate類別),雖然意義可能更精準了,但用一整個Date類別的概念去思考,程式碼會更容易理解,也就是所謂的內聚性(Cohesion)更高。 所以要替OOP就是「資料跟行為在一起」加個但書: 要以方便理解程式為前提,將資料和行為放在一起。

[好文轉載]哇操!你敢信?花式寫todo-list,body裡面一行都沒有也能搞?

[【前端動手玩創意】哇操!你敢信?花式寫todo-list,body裡面一行都沒有也能搞?](https://ithelp.ithome.com.tw/articles/10312056) ## 前情提要 如果說蟑螂怕拖鞋,老鼠愛大米,任何事物都有相生相剋的道理,那麼前端最害怕什麼呢? 恐怕就是todo-list。 這應該是前端的四大惡夢之一,並不是因為太難了,而是因為太簡單而且太無聊了, 不只無聊,還是每次教學都必須寫的一個磨難,簡直是瞬間殺死靈魂中隊前端的愛。 今天要來用不同風格寫出todo-list,把代辦事項寫出新滋味。 body裡面一行都沒有也能搞? 就是可以搞,讓我們馬上來欣賞這段有特別滋味的玩法!ε(*´・∀・`)з゙ ## 程式碼 ``` <!DOCTYPE html> <html> <head> <title>Todo List</title> </head> <body></body> <script> //渲染DOM AddHtml(); //資料內容 function AddHtml() { const Data = { h1: "Todo List", button: "Add", }; //主體的DOM const html = `<h1>${Data.h1}</h1> <input type="text" id="input" /> <button onclick="CheckNull()">${Data.button}</button> <ul id="list"></ul>`; //渲染至畫面上 document.body.innerHTML += html; } //邏輯確認:是否有輸入值 function CheckNull() { if (!input.value.trim("")) { return; } else { AddItem(); } } //新增代辦事項 function AddItem() { const li = `<li>${document.getElementById("input").value}</li>`; document.getElementById("list").innerHTML += li; input.value = ""; } </script> </html> ``` [可以貼到try it的地方執行看看效果](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_form_submit) ## 觀念筆記 所謂MVC架構就是模型、視圖、控制,背後其實有一個元素貫串任何程式,那就是:「邏輯」 每當你要下手寫一個程式卻不知道怎麼開始動手, 那就是邏輯沒有通順。 網頁不外乎就是畫面,以及資料,還有使用者的操作。 對於todo-list來說就是一個簡單的input畫面,使用者輸入的資料,點下按鈕送出的操作。 這段程式特地不寫任何一行body裡面的東西, 玩弄了一般人對於程式區分的概念。 用模板符的特性讓所有一切交給變數與函式處理,最後三個function: AddHtml、CheckNull、AddItem完美演繹了代辦清單這個網頁所需要構成的底層邏輯。 必須先加入畫面,然後確認使用者操作的條件,最後新增資料。 這樣子的流程對於新手或許不習慣,但是以邏輯面來看比一般人的寫法清晰許多。 這也是未來框架導入後,對資料流更敏感的培養練習。 ## 心得 無聊的todo-list竟然可以搞成這樣!? 真的是太有趣了(๑╹◡╹๑)! 原來前端的惡夢也可以變成寫不同風格的天堂,沒錯,寫程式就是這麼千變萬化! 重點是背後的邏輯抓到了,那麼想要怎麼寫,真的就是藝術的發揮。 請繼續關注, 跟著我們這個系列繼續動手玩創意!!未來還有更多更新鮮的花招呢(。◕∀◕。)

新手適用:重構程式碼的幾個簡單方向

## 介紹 程式碼重構,在不改變外部功能的情況下改進現有程式碼。它是寫程式的核心部分之一,不容忽視,否則您將無法獲得更好的程式碼。程式碼重構可以增強程式碼的可讀性、可維護性和可擴展性。它還能提高性能並提高開發人員的工作效率。 今天,我們將研究一些可以幫助您重構程式碼的技術。 原文出處:https://dev.to/documatic/5-code-refactoring-techniques-to-improve-your-code-2lia ## 如何整合Refactoring 在尋找改進重構的技術之前,讓我們看看如何將程式碼重構整合到您的工作流程中。您可以使用以下建議: - 你應該專門分配時間來重構程式碼。 - 將較大的重構問題分解為較小的重構問題進行管理。 - 嘗試讓整個團隊參與重構過程。 - 使用可以幫助您查找常見重構錯誤的自動化工具。 現在,讓我們從用於重構的技術開始。 --- ## 提取方法 此方法將程式碼轉換為單獨的方法/函數。這樣做是為了改善程式碼的結構和可讀性。它將長而復雜的程式碼提取為更小且更易於管理的方法。 要使用這種技術,我們首先需要找到一個執行有點複雜的特定任務的程式碼區塊。找到後,我們提取程式碼並放入新方法中。另外,請確保為該方法提供一個有意義的名稱。 **例子:** 重構前 ``` function calculateInvoiceTotal(items) { let total = 0; for (let i = 0; i < items.length; i++) { const item = items[i]; if (!item.quantity || !item.price) { console.error('Invalid item', item); continue; } const itemTotal = item.quantity * item.price; total += itemTotal; } return total; } ``` 重構後: ``` function calculateInvoiceTotal(items) { let total = 0; for (let i = 0; i < items.length; i++) { const item = items[i]; const itemTotal = calculateItemTotal(item); total += itemTotal; } return total; } function calculateItemTotal(item) { if (!item.quantity || !item.price) { console.error('Invalid item', item); return 0; } return item.quantity * item.price; } ``` 您可以看到我們如何將在 `for` 迴圈內執行的複雜程式碼轉換為另一種方法,以實現簡單性和可讀性。 --- ## 使用常數 此程式碼重構是為了編寫更清晰、更易讀的程式碼。直接寫數字可能會導致其他人感到困惑,因為他們的目的沒有定義。將硬編碼值轉換為具有有意義名稱的變數可以幫助其他人理解它。此外,您可以為其加入註解以進一步說名。它還可以幫助除錯並降低未來出錯的風險。 **例子:** 前 ``` if (temperature > 32) { // Do something if temperature is above freezing } ``` 後 ``` const int FREEZING_POINT = 32; if (temperature > FREEZING_POINT) { // Do something if temperature is above freezing } ``` ## 合併重複程式碼 重複或相同的程式碼可能出現在來自不同地方的程式碼中。此程式碼不需要完全相同,但它可以執行類似的任務或從原始程式碼擴展一點。重複的程式碼會導致幾個問題,包括增加維護成本、難以更改程式碼庫以及引入錯誤的更高風險。 在重構程式碼時,您必須注意重複程式碼。找到此類程式碼時,一種處理方法是將此類程式碼轉換為單個可重用的函數/方法。 例子: 前 ``` function calculateTotal(numbers) { let total = 0; for (let i = 0; i < numbers.length; i++) { total += numbers[i]; } return total; } function calculateAverage(numbers) { let total = 0; for (let i = 0; i < numbers.length; i++) { total += numbers[i]; } const average = total / numbers.length; return average; } ``` 後 ``` function calculateSum(numbers) { let total = 0; for (let i = 0; i < numbers.length; i++) { total += numbers[i]; } return total; } function calculateTotal(numbers) { return calculateSum(numbers); } function calculateAverage(numbers) { const total = calculateSum(numbers); const average = total / numbers.length; return average; } ``` 在之前的程式碼範例中,我們進行了求和並再次求和以求平均值。之後,我們將其替換為為兩者提供總和的函數。 --- ## 簡化方法 這與您正在尋找要優化的方法/功能時進行辨識非常相似。此技術可以幫助您減少程式碼行數。 此方法可以分解為更小的程式碼塊,您可以在要優化的函數中找到這些程式碼塊: - 刪除不必要的變數和表達式:可能有一些變數或表達式是您為了除錯而遺漏但忘記刪除的,例如 JavaScript 中的 console.log。 - 使用內建函數:有時使用庫或語言的內建函數會更好。因為可以用更少的程式碼實現相同的功能。 - 簡化條件語句:如果一個方法有複雜的條件語句,可以考慮通過組合條件或使用三元運算符來簡化它們。 ## 使用延遲載入 這是一種僅在需要時才載入物件的技術。這可以通過減少使用的內存量來提高應用程式的性能。這導致更快地載入應用程式。 這種技術在 Web 開發中非常流行。特別是對於像 React 這樣的 JavaScript 框架,您可以通過延遲載入來導入不同的元件。這也可以用於根據需要載入圖像。 **例子:** 前 ``` import React from 'react'; import MyComponent from './MyComponent'; const App = () => { return ( <div> <h1>My App</h1> <MyComponent /> </div> ); } export default App; ``` 後: ``` import React, { lazy, Suspense } from 'react'; const MyComponent = lazy(() => import('./MyComponent')); const App = () => { return ( <div> <h1>My App</h1> <Suspense fallback={<div>Loading...</div>}> <MyComponent /> </Suspense> </div> ); } export default App; ``` 在更新版本中,我們使用 `lazy` 函數異步導入 `MyComponent` 元件。這意味著該元件僅在實際需要時才載入,從而提高了我們應用程式的整體性能。我們還使用“Suspense”元件在載入元件時顯示後備 UI。 ## 結論 重構是任何想要提高程式碼質量、性能和可維護性的開發人員的基本實踐。通過花時間分析和優化您的程式碼,您可以消除冗餘、降低複雜性並建立更高效和可擴展的應用程式。 通過不斷審查和改進您的程式碼,您可以建立更健壯和更有彈性的應用程式。

10 個可以改善開發體驗的 VSCode 外掛

- 原文出處:https://dev.to/j471n/vs-code-extensions-to-take-your-coding-to-the-next-level-50od ## Documatic 此外掛將 [Documatic](https://www.documatic.com/) 引入 VSCode:使用簡單查詢快速搜尋大型程式碼庫。 Documatic 使用 AI 連結您的查詢和程式碼片段之間的關係,因此您不必知道要查找的確切關鍵字! **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=Tyriar.sort-lines) ![](https://i.imgur.com/KYutr9T.gif) ## Sort lines 此外掛允許您按字母或數字快速對程式碼進行排序,從而在處理大文件時節省時間。當您有要排序的資料時,這會非常方便。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=Tyriar.sort-lines) ![使用動畫](https://github.com/Tyriar/vscode-sort-lines/raw/HEAD/images/usage-animation.gif) ## TabNine 此外掛使用 AI 提供程式碼自動完成建議,可以幫助您節省時間並提高程式碼品質。它支援很多語言和框架。但是要小心使用它,因為它會佔用你系統的很多資源。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=TabNine.tabnine-vscode) ![Tabnine 主要完成](https://raw.githubusercontent.com/codota/tabnine-vscode/master/assets/completions-main.gif) ## **Template String Converter** 可以在程式碼編輯器中鍵入“${”時將普通字串轉換為模板字串。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=meganrogge.template-string-converter) ![鍵入一個美元符號然後在字串中打開大括號將引號轉換為反引號](https://raw.githubusercontent.com/meganrogge/template-string-converter/master/images/demo.gif) ## **Error Lens** ErrorLens 增強了語言診斷功能,突出顯示語言生成診斷的整行,並連結相關訊息。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens) ![演示圖片](https://raw.githubusercontent.com/usernamehw/vscode-error-lens/master/img/demo.png) ## **WakaTime** [WakaTime](https://wakatime.com/vs-code) 是一個開源 VS Code 外掛,用於從您的寫程式工時中,自動生成指標、分析和時間追蹤。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=WakaTime.vscode-wakatime) ![專案概覽](https://wakatime.com/static/img/ScreenShots/Screen-Shot-2016-03-21.png) ## **Chat** 通過使用此外掛,您可以在 VS Code 中與您的 Slack 和 Discord 團隊聊天。 * **安靜的通知**:聊天應用程式可能會讓人分心。此外掛使聊天變得有用、上下文相關且不會分散注意力。 * **豐富的格式**:分享 Markdown 程式碼片段,並在您的聊天訊息中加入表情符號。 * **本地外觀**:在您喜歡的主題和網格編輯器佈局中使用聊天。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=karigari.chat) ![截圖](https://raw.githubusercontent.com/karigari/vscode-chat/master/readme/Live%20Share%20Chat.gif) ## **SVG Preview** 允許您直接在 VS 程式碼中查看 SVG 文件。如果您在 vs 程式碼中打開 SVG 文件,那麼預設情況下它會顯示 SVG 程式碼。使用它後,您可以看到 SVG 的預覽。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=SimonSiefke.svg-preview) ![演示](https://github.com/SimonSiefke/vscode-svg-preview/raw/master/demo_images/demo.gif) ## **Headwind** Headwind 是用於 Visual Studio Code 的 Tailwind CSS 類排序器。它通過解析您的程式碼並重新打印類別標籤來強制執行一致的類別排序。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=heybourn.headwind) ![解釋器](https://github.com/heybourn/headwind/blob/master/img/explainer.gif?raw=true) ## **Material Design Palette Generator** [Material Design Palette Generator](https://marketplace.visualstudio.com/items?itemName=piyush-bhatt.vscode-mat-palette) 是一個 VSCode 外掛,用於生成 [material 調色板](https://material.io/design/color/the-color-system.html#tools-for-picking-colors)。 **⬇️** [**下載**](https://marketplace.visualstudio.com/items?itemName=piyush-bhatt.vscode-mat-palette) ![獲取從給定的十六進制顏色生成的完整調色板](https://raw.githubusercontent.com/piyush-bhatt/vscode-mat-palette/master/assets/readme/Primary.gif) --- 以上,簡單分享,希望對您有幫助!

使用 Tailwind 開發時,適合搭配的 4 款 VSCode 外掛

這些外掛都在這個 VSCode 外掛包裡面 [TailwindCSS Kit](https://marketplace.visualstudio.com/items?itemName=KalimahApps.tailwindcss-kit) 原文出處:https://dev.to/kalimahapps/4-vscode-extensions-i-use-for-tailwind-2him ## 1. [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) ![tailwind css 智能圖像](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4w36g7owmtrmljbesu24.png) Tailwind CSS IntelliSense 是一個強大的工具,可以幫助開發人員更快、更高效地編寫程式碼。它為 Tailwind CSS 類別提供即時建議,減少錯誤並提高程式碼品質。使用 IntelliSense,開發人員可以提高工作效率、縮短學習曲線並改進應用程式的可存取性。如果您是使用 Tailwind CSS 的開發人員,一定要試試這個強大的外掛。 ## 2. [Tailwind Fold](https://marketplace.visualstudio.com/items?itemName=stivo.tailwind-fold) ![tailwind 折疊擴展圖像](https://github.com/stivoat/tailwind-fold/raw/HEAD/images/docs/demo.gif) 在使用 Tailwind 時,此外掛非常有用。長長的類列表會使 html 有點混亂,此外掛提供了一種隱藏它們並僅在需要時顯示的好方法。除了預設功能外,這些選項經過細心設計,幾乎可以滿足任何偏好。例如,我喜歡在點擊線條而不是類別本身時展開類別。 ## 3. [Tailwind Documentation](https://marketplace.visualstudio.com/items?itemName=alfredbirk.tailwind-documentation) ![Tailwind 文件圖片](https://user-images.githubusercontent.com/11172530/163716626-8d74a1bb-f05b-4b45-aa12-70f66e0efad8.gif) Tailwind Documentation 提供對官方 Tailwind CSS 文件的快速存取。此外掛使開發人員能夠直接從 VSCode 編輯器中存取 Tailwind CSS 文件,而無需打開瀏覽器或離開編輯器。 ## 4. [Tailwind Config Viewer](https://marketplace.visualstudio.com/items?itemName=KalimahApps.tailwind-config-viewer) ![Tailwind 配置查看器圖像](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxwuaxi8v4o9olb4g06d.png) Tailwind 配置可能會令人困惑。它們可能呈指數級增長,並使用戶更難了解已解析的設定。這外掛使用戶能夠查看 **resolved** Tailwind 配置,它還會顯示任何與顏色相關的類別(text-\*、bg-\*、accent-\* ... 等)的顏色 --- 以上,簡單分享,希望對您有幫助!

# JS油猴系列-遮蔽廣告(D卡未登入)腳本、自定義新增名單

## 前情提要 逛論壇或網站常常有惱人的蓋板廣告,要馬就是要你登入、註冊, 要馬就是搞一堆課程的販售廣告, 對重視使用者體驗的人來說,真的是一場噩夢! 為了解決這個問題,我模擬了AdBlock的其中一個功能,刪除頁面上的元素! 乾乾淨淨才是王道阿。 ## 效果 按下ctrl+Q啟動刪除元素模式: ![](https://i.imgur.com/411nh3Q.png) 被選取的會加上邊框色彩,讓人確認是否要刪除: ![](https://i.imgur.com/zPEKMhC.png) 點選確認後: ![](https://i.imgur.com/nnOY4Ji.png) 煩人的元素就此消失在這個永恆的宇宙裡。 ## 觀念筆記 ### 套件一:toastr ```javascript= //toast.js cdn匯入 const toastJS = ` <link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>` $('body').append(toastJS); ``` ![](https://i.imgur.com/lNDch3V.png) [測試效果反應網站](https://codeseven.github.io/toastr/demo.html) ![](https://i.imgur.com/v95GUfO.png) [[十分鐘學習] toastr - 簡易提示訊息](https://ithelp.ithome.com.tw/articles/10197861) ### 套件二:SweetAlert2 ```javascript= //設定cdn使用Sweetalert套件 let Sweetalert2=`<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>` $('html').append(Sweetalert2) ``` ![](https://i.imgur.com/qUeTUlj.png) ![](https://i.imgur.com/FJH8EMX.png) 有提供很多API範例,還可以自己定義可愛的小動物XD [官方網站](https://sweetalert2.github.io/) ### 監聽鍵盤組合鍵 ``` document.addEventListener('keydown', function(e){ if(e.which==81 && e.ctrlKey==true){ //..... } ``` ### Object.assign 動態修改樣式 ![](https://i.imgur.com/AzZMRCc.png) [用JS動態修改CSS的三種寫法,花式JS玩弄樣式,嚇死你的同事!](https://codelove.tw/@JsLover0018/post/Ja64Kx) ## 油猴程式碼 ```javascript= // ==UserScript== // @name 刪除廣告元素 // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match *://*/* // @require https://code.jquery.com/jquery-3.6.3.min.js // @icon https://www.hexschool.com/ // @grant none // ==/UserScript== (function() { //--------------------------------------- // 宣告變數 let set let Check = true; let List=[] //設定選取的border色彩效果 let styleNeon = `@keyframes neon-color { from { filter: hue-rotate(0deg); } to { filter: hue-rotate(360deg); } }` $('style:last').append(styleNeon) //設定cdn使用Sweetalert套件 let Sweetalert2=`<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>` $('html').append(Sweetalert2) //使用者點選某個元素 執行刪除元素function function SetDeleteEl(e){ e.preventDefault(); set=e.target.class console.log(set) const border={ border:"4px dotted red" } const Neon={ animation: "neon-color 2.5s linear infinite" } const NoBorder={ border:"none" } const StopNeon={ animation: "" } Object.assign(e.target.style,border) Object.assign(e.target.style,Neon) //e.target.remove() if (Check==true){ Swal.fire({ title: '確定要刪除這個元素?', showDenyButton: true, showCancelButton: false, confirmButtonText: '確認', denyButtonText: `取消`, }).then((result) => { /* Read more about isConfirmed, isDenied below */ if (result.isConfirmed) { e.target.remove() List.push(e.target.className) localStorage.setItem('List',List); Check=false; Swal.fire('成功刪除此元素!', '', 'success') } else if (result.isDenied) { Check=false; Swal.fire('動作已取消', '', 'info') Object.assign(e.target.style,NoBorder) Object.assign(e.target.style,StopNeon) }; }); } //選取流程結束後 解開選取流程的事件綁定 $('body').unbind('click',SetDeleteEl) } //toast.js cdn匯入 const toastJS = ` <link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>` $('body').append(toastJS); // 當使用者按下Ctrl+Q 就執行主程序 document.addEventListener('keydown', function(e){ if(e.which==81 && e.ctrlKey==true){ RemoveListItem(); toastr.options = { // 參數設定[註1] "closeButton": false, // 顯示關閉按鈕 "debug": false, // 除錯 "newestOnTop": false, // 最新一筆顯示在最上面 "progressBar": false, // 顯示隱藏時間進度條 "positionClass": "toast-bottom-right", "preventDuplicates": false, // 隱藏重覆訊息 "onclick": null, // 當點選提示訊息時,則執行此函式 "showDuration": "300", // 顯示時間(單位: 毫秒) "hideDuration": "1000", // 隱藏時間(單位: 毫秒) "timeOut": "2000", // 當超過此設定時間時,則隱藏提示訊息(單位: 毫秒) "extendedTimeOut": "1000", // 當使用者觸碰到提示訊息時,離開後超過此設定時間則隱藏提示訊息(單位: 毫秒) "showEasing": "swing", // 顯示動畫時間曲線 "hideEasing": "linear", // 隱藏動畫時間曲線 "showMethod": "fadeIn", // 顯示動畫效果 "hideMethod": "fadeOut" // 隱藏動畫效果 } toastr.success( "已開啟刪除元素模式!" ); $('body').on('click',SetDeleteEl) Check=true }}) function RemoveListItem(){ if (localStorage.getItem('List')!=null){ item=localStorage.getItem('List').split(',') for (i=0;i<item.length;i++){ item[i]='.'+item[i] item[i]=item[i].replaceAll(' ','.') try{ document.querySelector(item[i]).remove()} catch{} } // item='.'+item // item=item.replaceAll(' ','.') // document.querySelector(item).remove() } } //-------------------------------------------------------- })(); ``` ## 心得 短短150行左右的程式碼,就寫得好辛苦!(汗 過去寫過很多次類似的東西,所以基本上沒有卡關的地方, 只是設計邏輯、嘗試的過程還是比想像的還要耗精神( ´•̥̥̥ω•̥̥̥ ) 但寫出來比過去快很多,也比過去好看超級多的。 給自己一個讚讚! 重新把localstorge複習一遍,Object.assign、套件使用等。 算是一個確確實實的實力鞏固過程。 ## 延伸 未來可以新增控制黑名單元素的UI。 可以新增、刪除,看有哪些元素被列入要刪除的黑名單。

[前端學習] 用JS動態修改CSS的三種寫法,花式JS玩弄樣式,嚇死你的同事!

## 前情提要 還在寫行內樣式醜醜的嗎?教你不用寫css檔案,使用javascript來動態修改樣式的招數! 這樣子處理的層次又更不一樣, 前端之路有你有我,馬上來看看這是怎麼完成的。 ## 要修改CSS怎麼做呢?物件儲存 首先樣式寫成物件 ```css= const die={ display:"none" } ``` 為什麼要寫成物件呢?修改一種,可能看不出來,修改很多樣式就能感受到, 物件這個儲存方式是有它特別的美感與好處的。 下面我來舉例: ```css= const wrapperStyle = { position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: '350px', backgroundColor: '#261d4a', borderRadius: '5px', transition: 'box-shadow .5s ease', overflow: 'hidden' }; ``` ## 語法介紹 Object.assign 使用範例 `Object.assign(element.style,Style)` element是你要修改的元素,Style是樣式寫的object 這是修改一個的情況,當像是上面很多屬性要改的話,我們物件與JS的好處就產生了! 直接使用迴圈來全部套入: ```javascript= const wrapper = document.getElementsByClassName('wrapper'); for (let i = 0; i < wrapper.length; i++) { Object.assign(wrapper[i].style, wrapperStyle); } ``` [MDN官網說明](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) [JS 原力覺醒 Day27 - JS 常用 API - Object.assign && Object.defineProperty](https://ithelp.ithome.com.tw/notifications) ## 還有沒有別的寫法? 有。 ``` document.getElementById("myElement").style.cssText = ` display: block; position: absolute; `; ``` 這樣寫也跟原生css寫起來差不多,比較舒服。 用這種比較分離畫面與程式的寫法, 體感上爽度更高。 就不會是找到元素後還要.style.display="none" 一直.屬性.進去點點點這樣。 ## 說好的三種呢? ``` function setStyle( objId, propertyObject ) { var elem = document.getElementById(objId); for (var property in propertyObject) elem.style[property] = propertyObject[property]; } setStyle('myElement', {'fontsize':'12px', 'left':'200px'}); ``` 這種寫成function的風格我也很愛,感覺很舒服,跟第一個的有點類似卻不太一樣。 這個是把迴圈弄再函式了,所以呼叫一次就會全部修改。 第一個則是把物件內的東西丟給迴圈,一次一次去做改動變化, 邏輯上一模一樣,手段跟風格差異而已唷。 [stackoverflow](https://stackoverflow.com/questions/3968593/how-can-i-set-multiple-css-styles-in-javascript) ## 心得 使用這個小技巧很有趣,之後我們會應用到「JS油猴系列-遮蔽廣告腳本,自定義新增名單」文章裡面。 當要寫腳本,很需要JS動態修改CSS的時候,這種小技巧就佔了很大的角色呢٩(๑•̀ω•́๑)۶! 是不是沒有想到居然可以用JS修改呀! 加上我認為比較差的寫法,就不只三種了呢。 趕快選一種喜歡的, 練習成自己的寶藏知識吧!

發文點子

分類: node類 腳本類 ajax類 頁面製作類 研究類 --------------------------------------------------------------------------- 1. 用JS動態修改CSS 的三種寫法 (完成) 2. 用node.js來寫聊天室--->進階篇章:對戰小遊戲 3. 串API練習-寫出qrcode製作器 4.串API練習-使用post完成"reurl.cc縮網址"功能 5. 串API練習-查詢股價用ajax,再用d3.js視覺化整理 6.寫出chrome離線小恐龍遊戲 7.JS油猴系列-遮蔽廣告腳本,自定義新增名單 (完成) 8.網頁製作入門-寫一個sitcom官網示範教學 9.瀑布流呈現-結合前端爬蟲抓PTT表特版圖片 10. hackmd視覺化-讓自己的筆記變成部落格 (X) :整理自己所學 11.把元素轉成圖片的三種方法:介紹html2canvas--->各種套件都介紹 12. jQuery CDN 掛點解決方案?簡單的 JavaScript 讓您有本地替代方案! https://mnya.tw/cc/word/1428.html --------------------------------------------------------------- 前端小試身手 1.至頂按鈕 自動隱藏且可直接使用的網頁回頂部按鈕 https://mnya.tw/cc/word/1735.html 2.捲動軸 3.用 JavaScript 做一個 Tooltips 功能 https://www.letswrite.tw/js-tooltips/ 4. Javascript,XML 轉 JSON https://www.letswrite.tw/xml-to-json/ -------------------------------------------------------------------------- CSS Tooltip Generator https://www.cssportal.com/css-tooltip-generator/ ![](https://i.imgur.com/lBtfanS.png)

[資源分享] 裝爆的VScode擴充套件,人生沒有擴充套件就是黑白的!

## code spell checker ![](https://i.imgur.com/dEaysXp.png) 不管是自己的英文程度太差,還是粗心大意,把英文字拼錯是家常便飯, 這款擴充套件就是來幫助你的救星! 使用code spell checker馬上會幫你標出奇奇怪怪的單字, 讓你確定沒有不小心把1跟l搞錯,就debug一整天的那種尷尬事件! ## live server ![](https://i.imgur.com/BdyRNga.png) 寫前端最需要的就是看到畫面٩(。・ω・。),و 每次如果都要自己在網址列找到檔案的位置才打開html, 那實在是太沒有工程師的效率了,簡直荒唐!! 當然要使用這款live server來架,馬上就可以看到自己的前端畫面, 而且儲存之後自動更新,根本神器。 ## material icon theme ![](https://i.imgur.com/cLgrQLt.png) 沒有什麼其他的,純粹就是好看! 裝了這款之後可以讓icon變得比較不一樣,整天都跟程式為伍, 當然就是要追求好看的圖圖。 ## prettier - code formatter ![](https://i.imgur.com/DDkFzb4.png) 超級讚的排版好物,懶得自己縮排了啦!就靠這款prettier, 讓你的程式從原本醜醜的排版, 最後,變成人類也能看懂的正常程式,必裝神器之一! ## 補充有人整理的 ### github ![](https://i.imgur.com/7X9O5Dz.png) [專案點這邊](https://github.com/Lin-jun-xiang/vscode-extensions-best/blob/main/README_%E4%B8%AD%E6%96%87.md) ### 影片分享 https://www.youtube.com/watch?v=xGE_M3R69YA [ Alex 宅抬槓 ] Visual Studio Code 外掛生存戰|從 2019 到 2020 前端開發必備安裝推薦 ## 心得 以上都是寫程式過程中會發現的需求,自然會想要找擴充來安裝,提升效率、美觀, 利用這些擴充功能,寫程式的體驗真的變得很舒服呢(๑•́ ₃ •̀๑)。 未來如果有什麼新的,也會持續補充,也歡迎大家分享討論唷~~

在 React 裡面,關於 Strict Mode 的簡單說明

`React.StrictMode` 是一個好用的元件,用於突出顯示應用程式中的潛在問題。就像 `<Fragment>` 一樣,`<StrictMode>` 不會渲染任何額外的 DOM 元素。在這篇文章中,我們將深入探討什麼是嚴格模式、它是如何運作的,以及為什麼你應該考慮使用看看。 原文出處:https://dev.to/codeofrelevancy/what-is-strict-mode-in-react-3p5b --- ## 什麼是 React 中的嚴格模式? 嚴格模式是一組開發工具,可幫助您在程式碼中找到潛在問題。當您在 React 應用程式中啟用嚴格模式時,您實際上是在告訴 React 打開一堆額外的檢查👀 和警告,以便幫助您寫出更好的程式碼。這些檢查和警告可以捕獲以下內容: 1. 有副作用的元件 2. 已棄用或不安全的生命週期方法 3. 某些內置函數的不安全用法 4. 列表中的重複鍵 ![嚴格模式](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10tfwojwoyip5ld20yec.gif) --- ## 啟用嚴格模式 在 React 應用程式中啟用嚴格模式非常簡單。您可以通過在主 `index.js` 文件中加入一行程式碼來實現: ``` import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); ``` ## 為應用程式的一部分啟用嚴格模式 您還可以為應用程式的任何部分啟用嚴格模式: ``` import { StrictMode } from 'react'; function App() { return ( <> <Header /> <StrictMode> <main> <Sidebar /> <Content /> </main> </StrictMode> <Footer /> </> ); } ``` 在這種情況下,嚴格模式檢查不會針對“頁首”和“頁腳”元件執行。但是,它們將在 `Sidebar` 和 `Content` 以及它們內部的所有元件上執行,無論它有多深層。 --- ## 嚴格模式只影響開發環境 請務必注意,嚴格模式對 React 應用程式的正式環境建置沒有影響。嚴格模式啟用的任何檢查或警告都不會出現在用戶看到的應用程式最終版本中。除此之外,嚴格模式會打開額外的檢查和警告,它可能會減慢您的開發環境速度。 ![嚴格模式只影響開發環境](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nu5kpm4ixxfesjdhv1cv.gif) --- ## 嚴格模式可以幫助你捕捉細微的錯誤 有時 React 應用程式中的錯誤可能很難追踪,特別是諸如 race conditions 或對元件狀態的不正確假設等細微問題。啟用嚴格模式的額外檢查和警告,您可以在這些錯誤導致嚴重問題之前發現它們。 --- ## 嚴格模式可以幫助您了解最新的最佳實踐 React 是一個快速發展的框架,最佳實踐會隨著時間而改變。啟用嚴格模式並留意它提供的警告和建議,您可以確保您的 React 程式碼遵循當前的最佳實踐。例如在渲染列表時使用 key 屬性,或者在 render() 中避免副作用。 --- ## 儘早發現潛在問題 嚴格模式可以在您的程式碼中發現可能在未來引起的問題,以免它們成為嚴重問題。比方說,它可以檢測並警告已棄用的生命週期方法以及對不再推薦的 [findDOMNode()](https://react.dev/reference/react-dom/findDOMNode) 的存取。 ![findDOMNode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awx9dnh9eexg4eb73wt2.png) ![findDOMNode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5hjs6oae3lj38mbhjwk.png) --- ## 防止常見錯誤 啟用嚴格模式,您可以避免一些隱晦的常見錯誤,例如:直接修改狀態而不是使用 setState()、使用未宣告變數。 --- ## 辨識不安全的生命週期 React Strict Mode 可以幫助辨識元件中不安全生命週期方法的使用。例如,它可以警告您使用 `componentWillUpdate` 和 `componentWillReceiveProps` 方法,這兩種方法都被認為是不安全的,將在 React 的未來版本中被刪除。 ![不安全生命週期](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s6d9qh4xjz16u9xlsle5.png) 假設您有一個元件,它使用 `componentWillReceiveProps()` 來根據傳入的 props 更新其狀態: ``` class BlackMamba extends React.Component { constructor(props) { super(props); this.state = { venom: props.venom }; } componentWillReceiveProps(nextProps) { this.setState({ venom: nextProps.venom }); } render() { return <div>{this.state.venom}</div>; } } ``` 在常規模式下,該元件會按預期工作,但在“React.StrictMode”下,您會在控制台中看到一條警告: > 警告:BlackMamba 使用 `componentWillReceiveProps`,這被認為是一種不安全的生命週期方法。請使用靜態的 getDerivedStateFromProps 。 --- ## 過時的字串引用 API 用法 嚴格模式還可以警告您過時的字串 `ref` API 的使用。該 API 已被官方棄用。您應該使用更安全、更易於使用的 `createRef` API。 ![過時的字串引用 API 用法](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gv8lf8ubk7vv4yg8m4qo.png) 比方說,您有一個元件使用這樣的字串引用: ``` import { Component } from "react"; import { createRoot } from "react-dom/client"; class BlackMamba extends Component { componentDidMount() { this.refs.venom.focus(); } render() { return ( <> <h1>Black Mamba</h1> <input ref="venom" /> </> ); } } const root = createRoot(document.getElementById("root")); root.render(<BlackMamba />); ``` 您不會在控制台中看到任何錯誤。 ![輸出](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trxw9auusgunit73rvzp.png) 當您像這樣在您的應用中啟用“React.StrictMode”時: ``` import { StrictMode, Component } from "react"; import { createRoot } from "react-dom/client"; class BlackMamba extends Component { componentDidMount() { this.refs.venom.focus(); } render() { return ( <> <h1>Black Mamba</h1> <input ref="venom" /> </> ); } } const root = createRoot(document.getElementById("root")); root.render( <StrictMode> <BlackMamba /> </StrictMode> ); ``` 您會在控制台中看到如下所示的警告: > Warning: A string ref, "venom", has been found within a strict mode tree. String refs are a source of potential bugs and should be avoided. We recommend using useRef() or createRef() instead. Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref ![輸出](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnf0qdctk8q7q9d1mzf0.png) 讓我們用 `createRef` API 修復它: ``` import { StrictMode, Component, createRef } from "react"; import { createRoot } from "react-dom/client"; class BlackMamba extends Component { constructor(props) { super(props); this.venom = createRef(); } componentDidMount() { this.venom.current.focus(); } render() { return ( <> <h1>Black Mamba</h1> <input ref={this.venom} /> </> ); } } const root = createRoot(document.getElementById("root")); root.render( <StrictMode> <BlackMamba /> </StrictMode> ); ``` 修理完成! ![輸出](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0pq7w11m292b3sh9e3aj.png) --- ## 過時的 Context API [舊版 Context API](https://legacy.reactjs.org/docs/legacy-context.html) 在 React 中已棄用,已被新的 Context API 取代。 React Strict Mode 可以幫助您檢測過時的 Context API 的任何使用情況,並鼓勵您切換到 [新 API](https://react.dev/reference/react/useContext) ![檢測遺留上下文 API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iowjhzc795mngti4ayo0.png) --- 如果您還沒有使用嚴格模式,那絕對值得使用看看! 以上簡單分享,希望對您有幫助!

新手推薦:最基本的 10 個 Git 指令與原理

Git 是軟體工程師最重要的工具之一,今天來學一點 Git 吧! 原文出處:https://dev.to/swordheath/git-the-basic-commands-every-developer-should-know-2m1e **什麼是 Git?** Git 是一個追蹤文件變更的版本控制系統。使用 Git 可以讓您保留所有更改的記錄並根據需要返回到特定版本。它使用方法簡單,佔用空間小,而且非常高效。它的分支模型使它有別於幾乎所有其他可用的 SCM。您可以使用 GitHub 或其他線上主機來儲存文件的備份及其修訂歷史。 **Git 的主要元件** 對我來說,Git 是在團隊專案中使用的絕佳工具,因為它有助於避免程式碼混淆,並帶來一個簡單而有效的工作流程。 ** Repository** Git 存儲庫(或簡稱 repo)包含所有專案文件以及整個修訂歷史記錄。您使用一個普通的資料夾(例如網站的根目錄夾)並告訴 Git 將它變成一個存儲庫。這將建立一個 .git 子文件夾,其中儲存了所有用於追蹤修改的 Git 元資料。簡而言之,存儲庫是您保存程式碼的地方。 **Commit** 要向存儲庫加入新程式碼,您需要進行提交,這是存儲庫在特定時間點的快照、將特定更改或一系列更改提交到存儲庫中的文件。 Git 的歷史紀錄由連續的提交組成。 **Branch** 分支用於儲存您的更改,直到它們準備就緒。在主分支(master)保持穩定的情況下,您可以在分支上工作。完成後,您可以將其與母版合併。最大的好處是您可以在一個存儲庫中擁有多個分支,並在需要時合併它們。 **Pull requests** 這是 Git 中用於在將更改合併到您的程式碼庫之前討論更改的技術。PR 不僅僅是一個通知;它是針對所提議功能的專門討論串。這在多人處理同一份程式碼時特別方便,允許開發人員檢查彼此的工作。 現在我們已經簡要討論了 Git 的主要元件,我想列出每個開發人員在開始使用 Git 之前必須知道的**10 個基本 Git 命令**。 **1。開始一個新的存儲庫** ``` git init ``` **2。分別設定作者姓名和電子郵件地址以用於您的提交** ``` git config - - global user.name “[name]” git config - - global user.email “[email address]” ``` **3。從遠程存儲庫下載現有程式碼** ``` git clone <https://name-of-the-repository-link> ``` **4。建立一個新分支** ``` git branch <branch-name> ``` **5。在 master 中合併分支** ``` git merge <branch-name> ``` **6。從遠程存儲庫取得更新** ``` git pull <remote> ``` **7。將文件加入到 Git 的暫存區** ``` git add <file or directory name> ``` **8。存儲庫的當前狀態** ``` git status ``` **9。將在 master 分支上所做的更改發送到您的遠程存儲庫** ``` git push [variable name] master   ``` **10。更改 head(在版本歷史記錄中加入一筆更新)** ``` git commit -m " Commit Message" ``` --- 這些是每個使用 Git 的人都必須知道的主要指令。Git 非常好用,指令數量也相當多。但是記住這些指令並不是一項艱鉅的任務——您只需要開始使用 Git,大多數指令都會憑直覺記住。

給新手參考:前端專案的檔案架構範例

在開發 Web 應用程式時建立可維護的檔案結構很重要,良好的架構有助於組織程式碼,並使其他開發人員了解您的 Web 應用程式結構。 原文出處:https://dev.to/noruwa/folder-structure-for-modern-web-applications-4d11 ### 設計檔案結構的一些技巧 - 了解您的 Web 專案的目的:為了弄清楚如何組織您的 Web 專案,您需要很好地了解專案需求 - 為您的文件夾和文件使用正確的命名慣例,它們應該描述您的 Web 應用程式的用途 ### 結構及說明 **Assets** assets 包含將在您的 Web 應用程式中使用的所有圖像、圖示、css 文件、字體文件等。自定義圖像、圖示、付費字體都放在這個文件夾中。 ![資產](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bosdpni04f4rhoscokrl.PNG) **Contexts** 當使用 React Js 作為您的前端 ui 庫時,context 文件夾存放所有跨元件和多個頁面使用的 react context 檔案。 ![上下文](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34ah8q7qbthfe5pbkcbf.PNG) **Components** components 文件夾包含應用程式的 UI。包含我們所有的 UI 元件,如導航列、頁腳、按鈕、視窗、卡片等等。 ![元件](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0fsm5cd609kxc1ydcv4b.PNG) ** Composables** 在 Vue 應用程式中,“Composables”是一種利用 Vue 的組合 API 來封裝和重用有狀態邏輯的功能。 **Data** 用來放會在不同部分和頁面中作為 JSON 文件使用的文本資料。這樣做將使資訊更新更容易。 ![資料 JSON](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/74ey2c253fveerw4ox3y.PNG) ![資料](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mybd8n92pxns26feb6qt.PNG) **Features** 包含每個頁面(身份驗證、主題、視窗)會用到的功能。例如,每個頁面可能都會用到視窗功能。 ![功能](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gljjlh0jgarivzabdamm.PNG) **Hooks** 讓 React 元件有狀態和生命週期特性的函數。我們還可以建立名稱以“use”開頭的自定義掛鉤,並可用於呼叫其他掛鉤。 ![掛鉤](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a84dq8pahtjgff63ru7e.PNG) **Layouts** 在定義網頁的總體外觀時,Layouts 文件夾會派上用場。它用於放置佈局的元件,例如側邊欄、導航欄和頁腳。如果您的 Web 應用程式有很多佈局,這個文件夾是保存它們的好地方。 ![佈局](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6h73gy0uruci8qlq5sjl.PNG) **Modules** Modules 文件夾處理應用程式中的特定任務。 ![模塊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/boeni6zfudcg14201s87.PNG) **Pages** pages 目錄包含您的 Web 應用程式畫面。 Next Js 和 Nuxt Js 等前端框架中的頁面目錄,會讀取目錄中的所有文件並自動為您建立路由設定。 ** Public** 直接在伺服器根目錄提供服務,包含不會更改的公共文件,例如 favicon.ico。 **Routes** routes 文件夾只是你的 web 應用程式中的一個地方,用於存放到不同頁面的路由路徑。 ** Utility/Utils** 該文件夾用於存放所有實用函數,例如 auth、theme、handleApiError 等。 ** Views** Views 文件夾類似於 pages 文件夾,用來放頁面的重複部分。 ### 結論 良好的檔案結構可以讓您和其他開發人員更快地找到文件並更輕鬆地管理它們。希望這篇文章對您有幫助!

JavaScript 語言中 13 個經常令新手困惑的設計

寫 JavaScript 偶爾會踩到一些小地雷,會讓新手思考很久很久,這邊整理一份清單! 原文出處:https://dev.to/codeofrelevancy/unexpected-moments-of-javascript-that-will-challenge-your-understanding-of-the-language-4834 --- 1️⃣ ``` 2 == [2] // true ``` 使用 `==` 做比較,可能會對變數型別做一些額外的轉換 在本例中,數字 2 被轉換為字串,陣列“[2]”也被轉換為字串。導致兩個值都是“2”。這就是為什麼比較結果為“真”。 通常建議使用 [嚴格相等運算符 `===`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality) 而不是 `==`避免意外結果.. 更多案例: ``` '123' == 123 // true 'foo' == NaN // false undefined == null // true NaN === NaN // false NaN == NaN // false 0 == null // false ``` --- 2️⃣ ``` [] == ![] // true ``` 將空陣列“[]”與通過取反建立的“布林值”進行比較(使用 [`!` 運算符](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT)) 一個非空陣列 `[]`。這種比較的結果是 `true`,乍一看似乎出乎意料。 在 JS 中,每個值在 `boolean` 上下文中可以是 `true` 或 `false`。空陣列是真值,這意味著它在“布林”上下文中被視為“真”。當我們對其應用 `!` 運算符時,它會轉換為 `false`。 另一方面,通過否定非空陣列建立的“boolean”值為“false”。當我們使用 `==` 運算符,JS 執行類型約束,這意味著它會在比較它們之前嘗試將值轉換為通用類型。因此,空陣列被轉換為 `false`,結果兩邊都是 `false`。最後,比較返回“true”。 探索更多: ``` ['a', 'b'] !== ['a', 'b'] // true ['a', 'b'] == ['a', 'b'] // false [1, 2] + [3, 4] // "1,23,4" ``` --- 3️⃣ ``` null == undefined // true ``` [double equals `==` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) 用於比較兩個值是否相等,同時忽略它們的資料類型。當使用雙等號運算符比較值“null”和“undefined”時,它們被認為是相等的,比較結果將為“true”。這是因為“null”和“undefined”都表示缺少值,並且在這種情況下彼此非常等價。 使用嚴格相等運算符: ``` null === undefined // false ``` --- 4️⃣ ``` typeof NaN // number typeof null // object ``` 在 JS 中,[typeof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) 是一個運算符,用於確定值或變數的類型。 [NaN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/NaN) 代表 **Not a Number** 是 JS 中的一個特殊值,代表一個 ` undefined` 或 `unrepresentable` 數值。 當您將 `typeof` 與 `NaN` 一起使用時,它將返回 `number`。這可能看起來很奇怪,但這是因為 `NaN` 在技術上是 JS 中的數字資料類型,儘管它代表的實際上不是數字。 當 typeof 應用於 null 時,它返回字串 object 。這是因為“null”被認為是一個表示空物件引用的特殊值。 `null` 本身不是一個物件,而是一個原始值。這被認為是 JS 語言設計中的一個怪癖。 探索更多: ``` typeof function(){} // "function" null instanceof Object // false ``` --- 5️⃣ ``` true == "1" // true false == "0" // true ``` JS 將字串“1”轉換為“布林”值“true”,將字串“0”轉換為“false”,因為任何非空字串都被視為_truthy_,而在另一端則被視為_falsy_。因此,比較變成了 true == true 是 true 和 false == false 是 true 。 探索更多: ``` 1 + true // 2 1 - true // 0 '' == false // true 0 == false // true true + false // 1 ``` --- 6️⃣ ``` "1" + 1 // "11" 2 + "2" // "22" "5" - 3 // 2 ``` 當您將 [+ 運算符](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Addition) 與“字串”和“數字”一起使用時,數字會被轉換到一個字串並連接到該字串。 如果可以將“字串”解析為“數字”,它將[減去](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Subtraction)“數字”來自“字串”。 所以, `"1" + 1` 變成字串 `"11"` `2 + "2"` 變成字串 `"22"` `"5" - 3` 變成數字 `2` 探索更多: ``` +"1" // 1 -"1" // -1 +true // 1 -true // -1 +false // 0 -false // -0 +null // 0 +undefined // NaN 1 / "2" // 0.5 "2" / 1 // 2 1 / 0 // Infinity -1 / 0 // -Infinity 3 * "abc" // NaN true > false // true undefined + 1 // NaN undefined - 1 // NaN undefined - undefined // NaN undefined + undefined // NaN null + 1 // 1 null - 1 // -1 null - null // 0 null + null // 0 Infinity + 1 // Infinity Infinity - 1 // Infinity Infinity - Infinity // NaN Infinity + Infinity // Infinity Infinity / Infinity // NaN ``` --- 7️⃣ ``` "b" + "a" + + "a" + "a" // "baNaNa" ``` 它連接字串 `b`、字串 `a`、由表達式 `+"a"` 和字串 `a` 產生的字串。 `+"a"` 將字串 `a` 強制轉換為計算結果為 `NaN`(不是數字)的數字,因為 `a` 不是有效數字。 當我們連接“b”、“a”、“NaN”(表示為空字串)和“a”時,我們得到字串“baNaNa”。 --- 8️⃣ ``` !{} // false {} == !{} // false {} == {} // false ``` 當我們將一個空物件“{}”與一個否定的空物件“!{}”進行比較時。驚嘆號 ! 是一個邏輯運算符,它否定物件的值,所以 !{} 返回 false 因為對像在 JS 中被認為是真實的。我們實際上是在將 `{}` 與 `false` 進行比較,結果是 `false` 值,因為它們在值或資料類型上不相等。 在最後一個表達式中,我們正在比較兩個空物件“{}”。儘管它們可能看起來相同,但它們是兩個獨立的物件,在內存中具有不同的引用,因此它們在值或資料類型上並不相等。最後,比較也會產生一個“假”值。 當您在用大括號`{}` 包裹的兩個物件之間使用**plus operator +** 時,它嘗試將物件連接為字串。 探索更多: ``` {} + [] === "" // false !!{} // true !![] // true [] + [] // "" [] + {} // "[object Object]" {} + [] // "[object Object]" {} + {} // "[object Object][object Object]" [] == false // true !!'' // false !!0 // false !!null // false !!undefined // false ``` --- 9️⃣ ``` 7 > 6 > 5 // false ``` 首先,“7 > 6”的計算結果為“真”,因為 7 大於 6。 接下來,評估“true > 5”。在 JS 中,`true` 強制轉換為數字 `1`,`false` 強制轉換為 `0`。所以 `1 > 5` 是 `false`,因為 `1` 不大於 `5`。 所以最後,`7 > 6 > 5` 等價於 `true > 5`,即 `false`。 探索更多: ``` 5 < 6 < 7 // true 0 > null // false ``` --- 1️⃣0️⃣ ``` Math.max() // -Infinity Math.min() // Infinity ``` `Math.max()` 和 `Math.min()` 是可用於分別查找一組數字中的最大值和最小值的函數。 當不帶任何參數呼叫時,`Math.max()` 返回 `-Infinity`,它表示 JS 中可能的最小 `number`,另一方面,`Math.min()` 返回 `Infinity`,它表示可能的最大 ` JS 中的數字`。 這種行為是有道理的,因為如果沒有提供數字,則 `Math.max()` 沒有要返回的最大數字,同樣,沒有為 `Math.min()` 返回的最小數字 --- 1️⃣1️⃣ ``` parseInt('08') // 8 parseInt('08', 10) // 8 parseInt('0x10') // 16 ``` `parseInt('08')` 將字串 `08` 轉換為整數 `8`。如果您要編寫“parseInt('08', 10)”,該函數仍將返回“8”。 這背後的原因是因為 parseInt 函數的第二個參數是指定要使用的編號系統的基數。比方說:`binary`、`octal`、`decimal`、`hexadecimal` 等。如果未指定基數,`parseInt` 將嘗試根據字串格式檢測基數。在上面的例子中,“08”被認為是一個八進制數,因為它以“0”開頭,所以它被轉換為十進制數“8”。 `parseInt('0x10')` 將 `hexadecimal` 字串 `0x10` 轉換為整數 `16`。基數也未指定,但前綴“0x”表示該數字應被視為“十六進制”數字,因此它被轉換為“16”作為十進制數。 探索更多: ``` parseFloat('3.14.15') // 3.14 parseFloat('0.0') // 0 ``` --- 1️⃣2️⃣ ``` (function(x) { delete x; return x; })(1); // 1 ``` 採用參數“x”的匿名函數。在函數內部,它試圖刪除 `x` 變數,但這是不可能的,因為 `x` 是函數參數,無法刪除。然後該函數返回 `x` 的值。 當使用參數“1”呼叫此函數時,函數內部的“x”值將設置為“1”。在這種情況下,刪除操作沒有效果,函數只是返回 `x` 的值,即 `1` --- 1️⃣3️⃣ ``` for (var i = 0; i < 3; ++i) { setTimeout(() => console.log(i), 1000); // returns 3 three times } for (let i = 0; i < 3; ++i) { setTimeout(() => console.log(i), 1000); // returns 0 1 2 } ``` 這是因為 `var` 在函數範圍內建立了一個綁定,所以在一秒超時後循環已經執行完了,因此你得到了 3 次 `3`。通過使用 `let`,您可以在塊作用域(循環)綁定變數,因此它返回您期望的值,因為 `i` 指的是該循環迭代中的值。 --- 簡單分享,希望對您有幫助!