🔍 搜尋結果:old

🔍 搜尋結果:old

寫了多年 React 之後,改寫 Svelte 的心得與感想

原文出處:https://dev.to/mikenikles/why-i-moved-from-react-to-svelte-and-others-will-follow-210l # React 多年來一直是我的首選 2015 年 10 月 14 日,我主持了 [首屆 React 溫哥華聚會](https://www.meetup.com/ReactJS-Vancouver-Meetup/events/225362860/)。當時我在一年中的大部分時間裡都在使用 React,並希望將志同道合的開發人員聚集在一起。 那時的 React,我敢說,是 web 前端世界的革命性的。與 jQuery、Backbone.js 或 Angular 1.x 等替代方案相比,使用 React 進行開發感覺直觀、清新且富有成效。就個人而言,隔離建置塊(又名元件)的想法真的很吸引我,因為它自然會導致結構化、組織良好且更易於維護的程式碼庫。 在接下來的幾年裡,我一直密切關注 Angular 2.x+、Vue 等,但沒有一個是值得跳槽的選擇。 # 然後我了解了 Svelte 我第一次了解 Svelte 是在 2018 年年中,也就是 3.0 版發布前將近一年(見下文)。 “[計算機,為我建置一個應用程式。](https://www.youtube.com/watch?v=qqt6YxAZoOc)”[Rich Harris](https://twitter.com/Rich_Harris) 讓我著迷Svelte。 > 如果您不熟悉 Svelte ([https://svelte.dev/](https://svelte.dev/)),請存取網站並花 5 分鐘閱讀介紹。 閱讀了嗎?真的?優秀👍 看完影片後,我心中的主要問題是是否值得學習 Svelte 並開始將其用於新專案甚至現有專案。平心而論,Svelte 給我留下了深刻的印象,但仍然不足以讓我完全接受它。 # Svelte 3.x 2019 年 4 月 22 日 - [Svelte 3:重新思考反應性](https://svelte.dev/blog/svelte-3-rethinking-reactivity) 是我一直在等待的博文。 > 請花一些時間閱讀博文並[觀看影片](https://www.youtube.com/watch?v=AdNJ3fydeao) - 這是關於電子表格的,但我保證它很有趣😉 為什麼這是一件大事?首先,Svelte 團隊一直在談論版本 3,我想看看它的實際應用。另一方面,Svelte 及其承諾比我第一次聽說 React 時更讓我興奮。 那時我指導 Web 開發人員,並花了很多時間讓他們加快 React 的速度。為了開發 React 應用程式,需要學習、理解並在一定程度上掌握 JSX、CSS-in-JS、Redux、create-react-app、SSR 和其他概念。 > 對於 Svelte,這些都不是必需的。 ``` <script> let name = 'world'; </script> <style> h1 { color: blue; } </style> <h1>Hello {name}!</h1> ``` 夠簡單嗎?我同意。事實上,它非常簡單,我將它推薦給我的 Web 開發新手。 ## 很快,那段程式碼發生了什麼? `script` 標籤是元件邏輯所在的位置。 `style` 標籤定義了這個元件的 CSS - 這些都不會洩漏到元件之外,所以我們可以安全地使用 h1 並且它只適用於這個元件。它是真正的 CSS,而不是偽裝成 CSS 的 Javascript 對像或偽裝成 CSS 的字串文字。 底部是元件的 HTML。使用帶有 `{myVariable}` 的變數。與 React 的 JSX 相比,Svelte 允許您使用正確的 HTML 標籤,例如 `for`、`class` 而不是 `forHtml` 和 `className`。請參閱 React 文件中的“[屬性差異](https://reactjs.org/docs/dom-elements.html#differences-in-attributes)”以獲取所有非標準 HTML 屬性的列表。 # 讓我們重建 React 示例 為了讓您了解 Svelte 與 React 的對比,讓我們重新建置 [https://reactjs.org/](https://reactjs.org/) 上列出的內容。 ## 一個簡單的元件 請參閱上面的程式碼片段。 ## 一個有狀態的元件 [互動演示](https://svelte.dev/repl/6e9ef214ae774287b21f902d7e6f0e68?version=3.16.6) ``` <script> let seconds = 0; setInterval(() => seconds += 1, 1000); </script> Seconds: {seconds} ``` React:33行 Svelte:6 行 ## 一個應用程式 [互動演示](https://svelte.dev/repl/817d413fd6c344bf859f0dbf8063de2f?version=3.16.6) ``` <script> /* App.svelte */ import TodoList from './TodoList.svelte'; let items = []; let text = ''; const handleSubmit = () => { if (!text.length) { return } const newItem = { text, id: Date.now(), }; items = items.concat(newItem); } </script> <div> <h3>TODO</h3> <TodoList {items} /> <form on:submit|preventDefault={handleSubmit}> <label for="new-todo"> What needs to be done? </label> <input id="new-todo" bind:value={text} /> <button> Add #{items.length + 1} </button> </form> </div> ``` ``` <script> /* TodoList.svelte */ export let items = []; </script> <ul> {#each items as item} <li key={item.id}>{item.text}</li> {/each} </ul> ``` React:66行 Svelte:43 行 ## 使用外部插件的元件 [互動演示](https://svelte.dev/repl/28f4b2e36e4244b8b23cae3d584c4c88?version=3.16.6) ``` <script> const md = new window.remarkable.Remarkable(); let value = 'Hello, **world**!'; </script> <svelte:head> <script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/2.0.0/remarkable.min.js"></script> </svelte:head> <div className="MarkdownEditor"> <h3>Input</h3> <label htmlFor="markdown-content"> Enter some markdown </label> <textarea id="markdown-content" bind:value={value} /> <h3>Output</h3> <div className="content"> {@html md.render(value)} </div> </div> ``` React:42行 Svelte:24 行 > 更少的程式碼 = 更少的錯誤 > 更少的程式碼 = 更好的性能 = 更好的用戶體驗 > 更少的程式碼 = 更少的維護 = 更多的時間來開發功能 # 我還喜歡 Svelte 什麼? ## 反應性 另一個強大的功能是 [反應式聲明](https://svelte.dev/tutorial/reactive-declarations)。讓我們從一個例子開始: ``` <script> let count = 0; $: doubled = count * 2; function handleClick() { count += 1; } </script> <button on:click={handleClick}> Clicked {count} {count === 1 ? 'time' : 'times'} </button> <p>{count} doubled is {doubled}</p> ``` 每當你有依賴於其他變數的變數時,用 `$: myVariable = [引用其他變數的程式碼]` 聲明它們。以上,每當 count 發生變化時,doubled 都會自動重新計算,並且 UI 會更新以反映新值。 ## Stores 在需要跨元件共享狀態的情況下,Svelte 提供了存儲的概念。 [教程很好地解釋了 store](https://svelte.dev/tutorial/auto-subscriptions)。無需閱讀冗長的教程 - store 就這麼簡單。 ### Derived stores 通常,一家 store 依賴於其他 store。這就是 Svelte 提供 derived() 來組合 store 的地方。 [有關詳細訊息,請參閱教程](https://svelte.dev/tutorial/derived-stores)。 ## 作為邏輯塊等待 好吧,這是一個非常優雅的。讓我們從程式碼開始([交互式演示](https://svelte.dev/repl/b9fc662a253443dc901ff189ce1cdd4b?version=3.16.7)): ``` <script> let githubRepoInfoPromise; let repoName = 'mikenikles/ghost-v3-google-cloud-storage'; const loadRepoInfo = async () => { const response = await fetch(`https://api.github.com/repos/${repoName}`); if (response.status === 200) { return await response.json(); } else { throw new Error(response.statusText); } } const handleClick = () => { githubRepoInfoPromise = loadRepoInfo(); } </script> <input type="text" placeholder="user/repo" bind:value={repoName} /> <button on:click={handleClick}> load Github repo info </button> {#await githubRepoInfoPromise} <p>...loading</p> {:then apiResponse} <p>{apiResponse ? `${apiResponse.full_name} is written in ${apiResponse.language}` : ''}</p> {:catch error} <p style="color: red">{error.message}</p> {/await} ``` 看到 HTML 中的“#await”塊了嗎?在真實世界的應用程式中,您將有一個加載元件、一個錯誤元件和在這種情況下呈現 API 響應的實際元件。嘗試在文本框中輸入無效的 repo 名稱以觸發錯誤案例。 # “等等,那……呢?” ## 開源元件? 當我向某人介紹 Svelte 時,我得到的主要回應是“但是生態系統、元件、教程、工具等呢?” 是的,開源 Svelte 元件遠不及 React 元件多。話雖如此,您多久使用一個開源 React 元件並在沒有任何問題或不必要的開銷的情況下集成它?我認為我們 Javascript 社區中的許多人已經變得過於依賴 `npm install ...` 來拼湊一個 web 應用程式。通常建置自己的元件,尤其是在 Svelte 中,可以減少整體花費的時間。我沒有資料可以證明,這是基於我個人的經驗。 不過,與此相關的是,對於任何願意重用開源元件的人來說,Svelte 元件的列表越來越多。 ## 正在找工作? 機會很多,請參閱 [https://sveltejobs.dev/](https://sveltejobs.dev/)。 Apple 的欺詐工程團隊正在[尋找 Svelte 開發人員](https://sveltejobs.dev/jobs/apple-senior-front-end-developer)(截至 2019 年 12 月)。 還要記住,與申請需要 React、Vue、Angular 等的工作相比,競爭要小得多。 # 然後,有 Sapper 來部署 Svelte 應用程式 開發應用程式只是整個蛋糕的一小部分——應用程式還需要部署。為此,Svelte 團隊提供了 [Sapper](https://sapper.svelte.dev/)。這本身就是一篇完整的帖子,所以現在請查看網站了解詳細訊息。 # 結論 每天,新的 Web 開發人員開始他們的旅程,許多人遇到的第一件事就是不確定首先要學什麼。我說未來就是簡單、快速的開發時間,我想不出比這更簡單、更快的事情了: ``` <script> let name = 'world'; </script> <style> h1 { color: blue; } </style> <h1>Hello {name}!</h1> ``` 以上分享,希望對您有幫助

[作業問題]HTML&CSS 第6課 Loading Page

您好,請問幾個問題。 1.為什麼我使用position:relative,網頁會出現很大的空白,我該如何解決。 2.使用絕對位置,我該如何讓我的網頁隨著比例縮放。 問題1 : ![](https://i.imgur.com/wzXvqGk.jpg) 問題2: ![](https://i.imgur.com/4a7OA6u.jpg) ![](https://i.imgur.com/BzUIBdJ.jpg) 這是網頁全開的時候 ![](https://i.imgur.com/YGNQAfx.jpg) HTML: ``` <!DOCTYPE html> <html> <head> <meta charset = "UTF-8"> <title>佳加安全帽</title> <link rel = "stylesheet" href = "style.css"> </head> <body class = "page"> <div class = "navbar"> <div class="container"> <div class = "logo"> <a href = "#"><img src = "jiajia.jpg"/></a> </div> <div class="menu"> <ul class="choose"> <li><a href = "">所有商品</a></li> <li><a href = "">特價商品</a></li> <li><a href = "">安全帽</a></li> <li><a href = "">藍芽耳機</a></li> <li><a href = "">裝備衣物</a></li> <li><a href = "">配件</a></li> <li><a href = "">包包</a></li> </ul> </div> <div class="user"> <ul> <li><a href = "">Log in 登入</a></li> <li>|</li> <li><a href = "">Sign up 註冊</a></li> </ul> </div> </div> </div> <div class="background"> <div class="content"> <h1>在危險的世界中,給你多一份安全</h1> </br> </br> <p>留下您的email,獲得新商品及最新優惠資訊</p> </br> <input type= "email" name = "email" value = "Your email"> </br> <input class="submit" type = "submit" name= "submit" value = "訂閱"> </div> </div> </body> </html> ``` CSS: ``` *{ margin: 0px; padding: 0px; list-style-type: none; text-decoration: none; } .navbar{ background-color: #272727; height: 50px; width: 100%; } .logo img{ height: 50px; } .menu{ position: relative; top: -50px; line-height: 45px; left: 500px; } .menu li{ float: left; } .menu a{ color: #D9B300; display: block; padding: 0 10px; } .menu a:hover{ background-color: #D9B300; color: #272727; } .user{ position: relative; top: -50px; left: 800px; line-height: 45px; } .user li{ float: left; color: #D9B300; } .user a{ color: #D9B300; display: block; padding: 0 10px; } .user a:hover{ background-color: #D9B300; color: #272727; } h1{ color: white; } p{ color: white; } .background{ background-image: url("motor.jpg"); background-size: cover; background-repeat: no-repeat; height: 660px; text-align: center; } .content input{ width: 400px; height: 40px; } .content h1{ font-size: 40px; } .content p{ font-size: 20px; } .content{ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .submit{ font-weight: bold; font-size: 20px; background-color: #D9B300; color: #272727; border-radius: 10px; border: 0px; } .submit:hover{ background-color: #272727; color: #D9B300; }

RE: 請教切板問題--切版觀念教學!實例code review!

## 前提 很棒的問題,很榮幸我也有辦法可以回答。 你好,稍微看了一下你的code,有些東西想要跟你討論、分享。 ## 解答 ### 修改完的效果 ![](https://i.imgur.com/3KBwL9M.png) ### 觀念方面 首先必須要稱讚你的野心,想要clone整個網頁,這是非常值得嘉獎的想法! 是我也會這樣練習,這種想法非常棒! 我覺得你這種學習態度非常好哦~~~ 針對code的問題, 我覺得你寫得有點亂,具體在於class與ID的名稱取名,我不知道你是否是直接copy人家的過來。 如果是這樣子,我覺得你可以試著自己重構, 如果不是的話,也建議你可以分區,使用註解來把哪一個區域是什麼標註起來, ![](https://i.imgur.com/hbMMJV8.png) 這對新手來說是個很好的習慣。 再來是你的分區我覺得滿亂的,加上似乎又有重複的div閉合標籤(? 不知道是你用copy的還是哪裡有問題,這部分要注意!! 做切版要先確定怎麼分割,你比較像是邊做邊分割,切的不是太好,導致排不太出來。 但這不是你的問題,這邊跟你分享他怎麼切,其實他這種板很簡單。 ### 邏輯方面 主要就是三個東西,wrap、container:main、side。 wrap的話就是設定寬度width以及margin:0 auto,製造一個居中效果。 container裡面有main與side就是你想要排的左跟右邊區。 只要container寫成dispaly:flex 與 justify-content: space around就可以了, 裡面的main寫flex: 0.66、然後side是flex:0.33 這樣會有平均分配的效果。 至於細節寬度就使用padding跟margin去調整。 ### HTML ``` <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="https://glitch.com/favicon.ico" /> <title>Hello world!</title> <!-- import the webpage's stylesheet --> <link rel="stylesheet" href="style2.css" /> <!-- import the webpage's javascript file --> <script src="/script.js" defer></script> </head> <body> <div class="wrap"> <div id="logo"> <a href="https://www.storm.mg/"> <img id="homepage" src="https://www.storm.mg/images/logo.svg" /> </a> </div> <div id="nav_menu"> <nav> <a class="nav_btn" href="https://new7.storm.mg/" ><img id="img1" src="https://www.storm.mg/images/logo_new7.svg" /></a> <a class="nav_btn" href="https://onepercent.storm.mg/" ><img id="img2" src="https://www.storm.mg/images/1percentstyle.svg" /></a> <a class="nav_btn" href="https://www.storm.mg/premium" ><img id="img3" src="https://www.storm.mg/images/vip_logo.png" /></a> <a class="nav_btn" href="#">新聞</a> <a class="nav_btn" href="#">評論</a> <a class="nav_btn" href="#">財經</a> <a class="nav_btn" href="#">生活</a> <a class="nav_btn" href="#">下班經濟學</a> </nav> </div> <div id="tag_title"> <a class="tag_link" href="https://www.storm.mg/category/118">政治</a> <a class="tag_link" href="https://www.storm.mg/category/22168" >公共政策</a > </div> <h1>北捷研擬早晚鳥4折票救內湖交通 高嘉瑜列3原因打臉:根本劃錯</h1> <div id="article_info"> <div id="article_info_name"> <a id="name" href="https://www.storm.mg/authors/313137/%E9%99%B3%E5%AC%BF%E5%A9%B7" >陳嬿婷</a > </div> <div id="article_info_time"> <span id="article_time">2023-02-13 16:16</span> </div> </div> </div> <div class="container2 wrap"> <div class="main"> <img src="https://image.cache.storm.mg/styles/smg-800x533-fp-wm/s3/media/image/2023/01/18/20230118-104054_U18448_M824647_96f1.jpeg?itok=xwGSqPL9" /> <p id="imgintro"> 民進黨立委高嘉瑜(見圖)認為,北市府放錯重點,需2年內讓汐止民生線、東環段動工,才有望根治長年未解的內湖交通問題。(資料照,柯承惠攝) </p> <p class="content_text"> 台北市內湖區近年發展快速,交通壅塞的問題成為各界關注的焦點,為解決內科交通問題,北市副市長李四川與相關單位討論,初步研擬推出北捷早晚鳥票,提供悠遊卡4折優惠,吸引通勤族捨棄汽機車,改搭捷運通勤,並鼓勵民眾在離峰時間上、下班。對此,民進黨立委高嘉瑜認為,北市府放錯重點,需2年內讓汐止民生線、東環段動工,才有望根治長年未解的內湖交通問題。 </p> <a id="link1" href="https://www.storm.mg/line/notify/login" >[啟動LINE推播] 每日重大新聞通知</a > <p class="content_text"> 高嘉瑜於<a id="fb" href="https://www.facebook.com/ntufishfans/posts/pfbid02AhK796XpShFigJjCsMe8vgDsGn8nCrzwXYs8aQdWPcbp86u92sXPJqZUXnnVadoZl" >臉書</a >發文,指出內科塞車問題,主要肇因於在上下班時間同時湧入高達15萬人次的跨區、跨縣市通勤者,而內科地區員工上班時間又有高達82%都集中在上午9時。雖然北市交通局預計推出早晚鳥票,並搭配企業彈性上下班,意圖使內科員工上班能錯開通勤尖峰時段,但事實上,前台北市長柯文哲早在2016年就曾提出為期3個月的「綠色運輸試辦計畫」,其內容就包括捷運早鳥優惠,結果仍是失敗收場。 </p> <p class="content_text"> 高嘉瑜也提到,彈性分流上下班很好,但優惠票誘因不足,她認為,企業端該如何溝通鼓勵彈性上下班?市府端又該如何推動共乘、減少一人一車?才是短期能立竿見影的方法,而長期而言,內科交通最終仍得靠完善捷運路網來拯救,如何解決現有文湖線運量不足且妥善率差及路線轉乘次數高等問題,才是當務之急。 </p> <p class="content_text"> 高嘉瑜也批評,目前民生線遙遙無期,汐東段亦未延伸至舊宗,北市府仍一拖再拖。她表示,行政院在今年1月已核定捷運汐東線,她也多次質詢跟強調,台北端的民生線應接續推動,至少此次汐東線也應先同步延伸至內湖舊宗路的「SB07站」,進而在未來與東環段接軌,串聯內湖、南港、社后、樟樹灣、保長坑及北五堵新市鎮等產業區。 </p> <p class="content_text"> 高嘉瑜說,但遺憾的是,經她近日再度詢問北市府關於「捷運汐東線之規劃,評估可否延伸」,得到的答覆卻是,「因民生線與汐東捷運、基隆捷運所採用之系統不同,須待汐東捷運具體規劃方案核定後,才會開始評估。」至今仍未能有明確定案。 </p> <p class="content_text"> 高嘉瑜強調,台北市長蔣萬安選前承諾東環段2年內動工,務必說到做到。她指出,環狀線東環段可串聯捷運紅線(象山)、藍線(永春)、綠線(松山),為東台北縱向捷運路網的重要建設,並有望根治長年未解的內湖交通問題,蔣萬安也曾在選前承諾2年內動工。她表示,自己會持續關注東環段進度,希望台北市政府可以更積極推動,中央加速進度儘快核定,別讓民眾一等再等。(相關報導:<a id="link2" href="https://www.storm.mg/article/4724935" >幕後》和柯文哲不一樣 高虹安的「軍機處」走自己的路</a >|更多文章) </p> </div> <div id="sidebar"> <div id="video_area"> <p class="sidebar_video">現正熱映中</p> <iframe id="smg_live_video" class="smg_live_video embed-responsive-item" src="https://www.youtube.com/embed/eJ4RErMLLh4?autoplay=&mute=1&version=3&loop=1" height="200" frameborder="0" allowfullscreen=""></iframe> </div> <div id="recommend"> <p class="sidebar_news sidebar_video">熱門新聞</p> </div> </div> </body> </html> ``` ### CSS ``` * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } #logo { margin: 0 auto; text-align: center; } #homepage { width: 169px; height: auto; } #img1 { width: 79px; height: 25px; margin: -8px 0 -5px; } #img2 { width: 79px; height: 25px; margin: -8px 0 -5px; } #img3 { width: 79px; height: 25px; margin: -8px 0 -5px; } #nav_menu { width: 100%; height: auto; border-top: 1px solid black; border-bottom: 1px solid #cccccc; text-align: left; } .nav_btn { display: inline-block; padding: 13px 15px 14px; letter-spacing: 3px; font-size: 16px; text-decoration: none; color: black; } #tag_title { border-left-width: 10px; border-left-style: solid; border-left-color: rgb(255, 56, 56); margin: 10px; } .tag_link { padding: 10px; color: black; text-decoration: bold; } #container { background: #f5f5f5; } #intro { margin: 10px; color: grey; font-size: 10px; } h1 { font-size: 32px; color: black; } #content { background: lightyellow; width: 800px; padding: 5px 30px 20px; } .content_text { padding: 15px 0px; } #artice_info, #article_info_name, #article_info_time { display: inline-block; margin: 10px; } #name { color: red; font-size: 16px; padding: 5px; } #article_time { color: black; font-size: 16px; padding: 5px; } #sidebar { flex:0.33; width: 300px; margin-left: 20px; padding: 0px 30px; } .main{ flex: 0.66; } #video_area, #recommend { border-top-width: 2px; border-top-style: solid; border-top-color: rgb(0, 0, 0); } .sidebar_news{ border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: grey; padding: 10px 10px 10px 0px; } #img_area { min-height: 420px; position: relative; } #link1 { color: grey; padding: 0px 25px; } #link2 { color: grey; } #fb { color: red; } .container2{ display: flex; justify-content: space-around; } .wrap { width: 1250px; margin: 0 auto; padding: 0px 39px; } .sidebar_video{ margin-top: 10px; font-size: 20px; letter-spacing: 5px; color: #ff3838; margin-bottom: 10px; } .smg_live_video{ margin-bottom: 10px; } ``` ## 後記 以上,很不錯的練習,整體而言做得很好! 希望未來可以一起繼續進步哦~~ 另外也還是要感謝站長創立這個網站,我從加入的第一天到現在都還是很喜歡哦。 現在站長也有[線上諮詢](https://codelove.tw/coaching)的服務,歡迎各位有需求,投資自己,跟高手學習! 時間就是金錢,掌握關鍵的學習方法其實比胡搞瞎搞重要! shout out to my man 阿川。

7 個好用的 React Hooks:可以在很多專案直接使用

Hooks 是 React 最強大的功能之一。 它們使我們能夠輕鬆地在應用程式的元件中重用功能。掛鉤的最大優點在於它們的可重用性——您可以跨元件和專案重用掛鉤。 以下是我在每個 React 專案中重複使用的七個最重要的鉤子。今天就試一試,看看它們在建置您自己的 React 應用程式時是否有幫助吧。 原文出處:https://dev.to/webdevhero-com/7-react-hooks-for-every-project-1jdo --- 在我們開始之前,要先澄清一下:並非每個自定義 React 鉤子都需要由您編寫。事實上,我將提到的所有鉤子都來自一個庫“@mantine/hooks”。 Mantine 是一個很棒的第三方庫,其中包含這些鉤子等等。他們將為您的 React 應用程式加入您能想到的幾乎所有重要功能。 您可以在 [mantine.dev](https://mantine.dev) 查看“@mantine/hooks”的文件。 ## `useIntersection` 鉤子 當用戶在您的應用程式中向下滾動頁面時,您可能想知道某個元素何時對他們可見。 例如,您可能希望僅在用戶看到特定元素時才啟動動畫。或者,您可能希望在他們向下滾動頁面一定程度後,顯示或隱藏元素。 ![use intersection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zilwvvdjppw9uz82iixo.gif) 要獲取有關元素是否可見的訊息,我們可以使用 **Intersection Observer API。**這是瀏覽器中內建的 JavaScript API。 我們可以使用純 JavaScript 單獨使用 API,但要知道有關特定元素是否在其滾動容器內,有個好方法是使用 useIntersection 掛鉤。 ``` import { useRef } from 'react'; import { useIntersection } from '@mantine/hooks'; function Demo() { const containerRef = useRef(); const { ref, entry } = useIntersection({ root: containerRef.current, threshold: 1, }); return ( <main ref={containerRef} style={{ overflowY: 'scroll', height: 300 }}> <div ref={ref}> <span> {entry?.isIntersecting ? 'Fully visible' : 'Obscured'} </span> </div> </main> ); } ``` 要使用它,我們需要做的就是在我們的元件中呼叫鉤子,並提供一個根元素。 Root 是滾動容器,可以使用 useRef 掛鉤將其作為 ref 提供。 `useIntersection` 回傳一個我們傳遞給目標元素的 ref,我們想要觀察其在滾動容器中的交集。 一旦我們有了對元素的引用,我們就可以追蹤元素是否相交。在上面的範例中,我們可以根據 entry.isIntersecting 的值查看元素何時被遮擋或何時完全可見。 您可以傳遞其他參數,這些參數允許您配置與目標可見百分比相關的**閾值**。 ## `useScrollLock` 鉤子 另一個與滾動相關的鉤子是 useScrollLock 鉤子。這個鉤子非常簡單:它使您能夠鎖定 body 元素上的任何滾動。 我發現當您想在當前頁面上顯示疊加層或跳出視窗,並且不想讓用戶在後台頁面上上下滾動時,它會很有幫助。這使您可以將注意力集中在視窗上,或允許在其自己的滾動容器內滾動。 ``` import { useScrollLock } from '@mantine/hooks'; import { Button, Group } from '@mantine/core'; import { IconLock, IconLockOpen } from '@tabler/icons'; function Demo() { const [scrollLocked, setScrollLocked] = useScrollLock(); return ( <Group position="center"> <Button onClick={() => setScrollLocked((c) => !c)} variant="outline" leftIcon={scrollLocked ? <IconLock size={16} /> : <IconLockOpen size={16} />} > {scrollLocked ? 'Unlock scroll' : 'Lock scroll'} </Button> </Group> ); } ``` `useScrollLock` 將用戶的滾動鎖定在頁面上的當前位置。該函數回傳一個陣列,它可以被解構,如上面的程式碼所示。 第二個值是一個允許我們鎖定滾動的函數。另一方面,第一個解構值是一個布林值,它告訴我們滾動條是否已被鎖定。 這個值很有用,例如,如果你想在滾動鎖定時顯示某些內容或告訴用戶它已被鎖定。您可以在下面的示例中看到,當滾動條被鎖定或解鎖時,我們會在我們的按鈕中進行指示。 ![use scroll lock](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wywccv7uexfrhfgayqj9.gif) ## `useClipboard` 鉤子 在許多情況下,您希望提供一個按鈕,允許用戶將內容複製到他們的剪貼板,這是存儲複製文本的地方。 一個很好的例子是,如果您的網站上有一個程式碼片段,並且您希望用戶輕鬆複製它。為此,我們可以使用另一個 Web API——**剪貼板 API**。 `@mantine/hooks` 為我們提供了一個方便的 `useClipboard` 鉤子,它回傳幾個屬性:`copied`,它是一個布林值,告訴我們是否已使用鉤子將值複製到剪貼板,以及` copy` 函數,我們可以將我們喜歡的任何字串值傳遞給它以進行複制。 在我們的範例中,我們想複製一個程式碼片段,供我們的用戶粘貼到他們喜歡的地方,如下面的影片所示: ![使用剪貼板](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6n0xd02vdg65bbfmb2xh.gif) ## useClipboard demo 當他們點擊我們指定的複制按鈕時,我們呼叫我們的 `copy` 函數,將程式碼片段傳遞給它,然後顯示一個小複選標記或向他們表明文本已被複製的東西。 巧妙的是 `useClipboard` 掛鉤帶有 **超時值**。在給定的超時時間(以毫秒為單位)之後,複製的狀態將被重置,向用戶顯示他們可以再次復製文本。 ## `useDebouncedValue` 鉤子 如果您的應用程式中有搜尋輸入,下一個鉤子“useDebouncedValue”是必不可少的。 每當用戶使用輸入執行搜尋時,搜尋操作通常涉及對 API 的 HTTP 請求。 您將遇到的一個典型問題是每次擊鍵都會執行查詢(請求),尤其是如果您希望用戶在鍵入時接收搜尋結果。即使對於一個簡單的搜尋查詢,也不需要在用戶完成輸入他們想要的內容之前執行這麼多請求。 這是 useDebounceValue 掛鉤的一個很好的用例,它對傳遞給它的文本應用「防抖」功能。 ``` import { useState } from 'react'; import { useDebouncedValue } from '@mantine/hooks'; import { getResults } from 'api'; function Demo() { const [value, setValue] = useState(''); const [results, setResults] = useState([]) const [debounced] = useDebouncedValue(value, 200); // wait time of 200 ms useEffect(() => { if (debounced) { handleGetResults() } async function handleGetResults() { const results = await getResults(debounced) setResults(results) } }, [debounced]) return ( <> <input label="Enter search query" value={value} style={{ flex: 1 }} onChange={(event) => setValue(event.currentTarget.value)} /> <ul>{results.map(result => <li>{result}</li>}</ul> </> ); } ``` 您使用 useState 將輸入的文本儲存在一個狀態中,並將狀態變數傳遞給 useDebouncedValue 。 作為該掛鉤的第二個參數,您可以提供一個等待時間,即值被「反抖」的時間段。反抖使我們能夠執行更少的查詢。 您可以在下面的影片中看到結果,用戶在其中鍵入內容,並且僅在 200 毫秒後,我們才能看到去抖值。 ![使用去抖值](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qfb5kqb6bxbkqfvog1hw.gif) ## `useMediaQuery` 鉤子 我一直使用的另一個非常有用的鉤子是 useMediaQuery 鉤子。 Media Queries 在純 CSS 中使用,`useMediaQuery` 鉤子允許我們訂閱我們傳遞給鉤子的任何媒體查詢。 例如,在我們的元件中,假設我們想要顯示一些文本或根據特定螢幕寬度(例如 900 像素)更改元件的樣式。我們像在 CSS 中一樣提供媒體查詢,並且 useMediaQuery 回傳給我們一個 true 或 false 的 matches 值。 ``` import { useMediaQuery } from '@mantine/hooks'; function Demo() { const matches = useMediaQuery('(min-width: 900px)'); return ( <div style={{ color: matches ? 'teal' : 'red' }}> {matches ? 'I am teal' : 'I am red'} </div> ); } ``` 它用 JavaScript 告訴我們媒體查詢的結果,這在我們想要使用 `style` 屬性在 JSX 中直接更改樣式時特別有用,例如。 ![使用媒體查詢](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7al1apywiq08ntgs4d8l.gif) 簡而言之,對於少數無法使用 CSS 處理媒體查詢的情況,這是一個必不可少的鉤子。 ## `useClickOutside` 鉤子 下一個掛鉤 - `useClickOutside` - 可能看起來很奇怪,但當您真正需要它時,您會發現它的重要性。 當你開發一個下拉菜單,或者在頁面內容前面彈出,並且之後需要關閉的東西時,這個鉤子是必不可少的。通過單擊按鈕打開這些類型的元件之一非常容易。關閉這些元件有點困難。 為了遵循良好的 UX 實踐,我們希望任何阻礙用戶視圖的東西都可以通過單擊元素外部輕鬆關閉。這正是 useClickOutside 掛鉤讓我們做的。 當我們呼叫 useClickOutside 時,它會返回一個 ref,我們必須將其傳遞給我們想要檢測點擊的外部元素。通常該元素將由一個布林狀態片段控制,例如我們在下面的示例中的狀態(即值“opened”)。 ``` import { useState } from 'react'; import { useClickOutside } from '@mantine/hooks'; function Demo() { const [opened, setOpened] = useState(false); const ref = useClickOutside(() => setOpened(false)); return ( <> <button onClick={() => setOpened(true)}>Open dropdown</button> {opened && ( <div ref={ref} shadow="sm"> <span>Click outside to close</span> </div> )} </> ); } ``` `useClickOutside` 接受一個回調函數,該函數控制當您實際單擊該元素外部時發生的情況。 在大多數情況下,我們想做一些非常簡單的事情,就是關閉它。為此,您可能需要一個狀態設置器(如 `setOpened`)並向其傳遞一個 false 值,然後隱藏您覆蓋的內容。 ![use click outside](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4jidp380brennyatol7w.gif) ## `useForm` 鉤子 在這個列表中,我最喜歡和最有用的鉤子是 `useForm` 鉤子。 這個鉤子專門來自 Mantine,涉及從庫中安裝一個特定的包:`@mantine/form`。它會為您提供在 React 中建立表單所需的一切,包括驗證輸入、顯示錯誤訊息以及在提交表單之前確保輸入值正確的能力。 `useForm` 接受一些初始值,這些初始值對應於您在表單中的任何輸入。 ``` import { TextInput, Button } from '@mantine/core'; import { useForm } from '@mantine/form'; function Demo() { const form = useForm({ initialValues: { email: '' }, validate: { email: (value) => (/^\S+@\S+$/.test(value) ? null : 'Invalid email'), }, }); return ( <div> <form onSubmit={form.onSubmit((values) => console.log(values))}> <TextInput withAsterisk label="Email" placeholder="[email protected]" {...form.getInputProps('email')} /> <Button type="submit">Submit</Button> </form> </div> ); } ``` `useForm` 的最大好處是它的助手,例如 `validate` 函數,它接收輸入到每個輸入的值,然後允許您建立驗證規則。 例如,如果您有一個電子郵件輸入,您可能有一個正則表達式來確定它實際上是否是一個有效的電子郵件(如您在上面的程式碼中所見)。如果沒有,那麼您可以顯示一條錯誤訊息並阻止提交表單。 ![使用表格](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n13l1gqejzx6y227p0j2.gif) 您如何獲取已輸入到表單中的值? Mantine 提供了一個非常方便的助手,叫做“getInputProps”,你只需提供你正在使用的輸入的名稱(比如電子郵件),它就會自動設置一個 onChange 來追蹤你在表單中輸入的值. 此外,為了處理表單提交,並在其值未通過驗證規則時阻止送出,它有一個特殊的 `onSubmit` 函數,您可以將其包裹在常規的 onSubmit 函數中。除了應用驗證規則之外,它還會負責在表單事件上呼叫 `preventDefault()`,這樣您就不必手動執行此操作。 我只用了這個鉤子的基本功能,但我強烈建議您在下一個專案中使用它。傳統上,表單很難正常工作,尤其是需要驗證和可見錯誤訊息的表單。 `useForm` 讓它變得異常簡單! --- 以上,簡單分享,希望對您有幫助。

給自學 JavaScript 的初學者:7 個可以學習基本觀念的 Github 專案

使用這些 github repo 成為更好的前端開發人員。 原文出處:https://dev.to/hy_piyush/7-github-repositories-that-every-front-end-developer-must-know-300l ## Clean Code JavaScript 一些能幫助您程式碼更簡潔的開發觀念。 GitHub 連結:https://github.com/ryanmcdermott/clean-code-javascript ## JavaScript Algorithms and Data Structure 用 JavaScript 實作的演算法和資料結構,有解釋和進一步閱讀的連結 包含許多流行演算法和資料結構的 JavaScript 範例。 每個演算法和資料結構都有自己單獨的 README,帶有相關的解釋和進一步閱讀的連結。 GitHub 連結:https://github.com/trekhleb/javascript-algorithms ## You Don’t Know JavaScript 這是一個關於 JavaScript 的系列叢書。這是一系列深入探討 JavaScript 語言核心機制的書籍。 GitHub 連結:https://github.com/getify/You-Dont-Know-JS ## NodeJS Best Practice 這個存儲庫是對 Node.js 最佳實踐的總結和管理。這將幫助許多開發人員獲得有關 NodeJS 後端開發的進階知識。 GitHub 連結:https://github.com/goldbergyoni/nodebestpractices ## Frontend Checklist 適用於現代網站和專業開發人員的完美前端清單。它基於前端開發人員多年的經驗,並加入了一些其他開源清單。 GitHub 連結:https://github.com/thedaviddias/Front-End-Checklist ## Free For Dev 對 DevOps 和基礎設施開發,具有免費方案的 SaaS、PaaS 和 IaaS 產品列表。 不過,此列表的內容只對基礎架構開發人員(系統管理員、DevOps 從業者等)有用。 GitHub 連結:https://github.com/jixserver/free-for-dev ## DSA in JavaScript 解釋和實作的資料結構和演算法。 GitHub 連結:https://github.com/amejiarosario/dsa.js-data-structures-algorithms-javascript

都要 2023 年了還在用 console.log 嗎?來看看 10 個 console 進階用法!

寫 JavaScript 時,仍在使用 console.log 來除錯抓蟲? 是時候**升級你的技能**並學習 JavaScript console 物件的全部功能了。 從 console.table 到 console.time,這些進階方法和技巧將改善您 **debug 訊息的品質和可讀性**,讓您更輕鬆地故障排除和修復問題。 在 2023 年成為 JavaScript 除錯高手吧! - 原文出處:https://dev.to/naubit/why-using-just-consolelog-in-2023-is-a-big-no-no-2429 ## 😞 問題 僅使用 console.log 的最大問題之一是,它會使程式碼混亂且難以閱讀。此外,它本身的資訊量不是很大。它只是輸出你傳遞給它的任何內容的值,沒有任何上下文或其他資訊。 所以,這裡有十個你應該知道的 JavaScript console 物件方法和技巧,值得了解一下! ## 1️⃣ console.table 此方法以可讀且易於理解的格式,輸出資料表格。console.table 不是只顯示陣列或物件,而是以表格格式顯示,使它更易於瀏覽和理解。 ``` // Output an array of objects as a table const users = [ { id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Doe' } ]; console.table(users); ``` 這將以表格格式輸出 users 陣列,每個物件的屬性作為列,物件作為行。 ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hek6gxo4x73b6mvmlawr.png) ## 2️⃣console.group console.group 和 console.groupEnd。這些方法可以在控制台中,創建嵌套的可摺疊資料組。**這對於組織和構建 debug 訊息非常有用**,讓您可以輕鬆查看程式碼不同級別發生的情況。 ``` console.group('User Details'); console.log('Name: John Doe'); console.log('Age: 32'); console.groupEnd(); ``` 這將在 console 中創建一個嵌套的、可摺疊的資料組,標題為“使用者詳細資訊”。組內的日誌消息將縮進並分組在一起。 ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ybn1uwvyltjzxcaaytx.png) ## 3️⃣console.time console.time 和 console.timeEnd 可以測量執行程式碼所需的時間。這對於識別程式中的性能瓶頸、效能優化非常有用。 ``` console.time('Fetching data'); fetch('https://reqres.in/api/users') .then(response => response.json()) .then(data => { console.timeEnd('Fetching data'); // Process the data }); ``` 這將測量「從特定 URL 獲取資料並解析 JSON 回應」所需的時間。耗用時間會在控制台中輸出。 ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f3hdvnz2of3an1a21j3c.png) ## 4️⃣console.assert 此方法允許您在程式碼中寫 assertions,這些是應該始終為 true 的語句。如果 assertions 失敗,console.assert 將在控制台中輸出錯誤消息。**這對於除錯抓蟲、確保程式碼正常運作非常有用。 ``` function add(a, b) { return a + b; } // Test the add function const result = add(2, 3); console.assert(result === 5, 'Expected 2 + 3 = 5'); ``` 如果 add 函數在給定輸入 2 和 3 時未返回預期結果 5,就在控制台中輸出錯誤訊息。 ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y25c157xwhasxnaiakd5.png) ## 5️⃣設置日誌樣式 使用 `console` 物件輸出樣式和顏色。 `console` 物件**允許您輸出不同顏色和樣式的文字**,使您的除錯輸出更具可讀性和更容易理解。 您可以在 console.log 語句中使用 %c 佔位符來指定輸出文字的 CSS 樣式。 ``` console.log('%cHello world!', 'color: red; font-weight: bold;'); ``` 這將輸出文字“Hello world!”,並使用指定的 CSS 樣式,以紅色和粗體顯示。 ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1p82u116icnlodu046nr.png) ## 6️⃣console.trace 使用 `console.trace` 方法輸出堆疊追踪(stack trace)。這對於理解程式碼中的執行流程、識別**特定日誌消息的來源非常有用。** ``` function foo() { console.trace(); } function bar() { foo(); } bar(); ``` 這將在控制台中輸出堆疊跟踪,顯示導致 `console.trace` 呼叫的函數呼叫序列。看起來像這樣: ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zx16nee1mp0avh04msri.png) ## 7️⃣console.dir 使用 `console.dir` 方法以分層格式輸出物件的屬性。這對於**探索物件的結構**、查看其屬性和方法非常有用。 ``` const obj = { id: 1, name: 'John Doe', address: { street: '123 Main St', city: 'New York', zip: 10001 } }; console.dir(obj); ``` 這將以分層格式輸出 `obj` 物件的屬性,允許您查看物件的結構及其所有屬性和值。 ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ihgkg5e4wxznpaqzb8jr.png) ## 8️⃣console.count 使用 `console.count` 方法計算特定日誌消息的輸出次數。這對於**追蹤特定程式碼路徑的執行次數**以及識別程式碼中的熱點很有用。 ``` function foo(x) { console.count(x); } foo('hello'); foo('world'); foo('hello'); ``` 這將在控制台中輸出字串“hello”,然後是數字 1。然後它將在控制台中輸出字串“world”,然後是數字 1。最後,它會再次輸出字符串“hello”,然後出書數字 2(因為它被呼叫了兩次)。 ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cx7n8aargexpq1pvqj6n.png) ## 9️⃣console.clear 使用 `console.clear` 方法清除控制台輸出。這能保持您的除錯輸出**有條理和整潔**,讓您更容易專注於您感興趣的訊息。 ``` console.log('Hello world!'); console.clear(); console.log('This log message will appear after the console is cleared.'); ``` 這將輸出字串 “Hello world!”,接著一個空行(因為控制台已清除)。然後它會輸出字串 “This log message will appear after the console is cleared.” ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ihzapi1gcin6gtqa600v.png) ## 1️⃣0️⃣console.profile 使用 `console.profile` 和 `console.profileEnd` 方法來衡量程式碼的性能。這對於**識別性能瓶頸和優化代碼**、提高速度和效率非常有用。 ``` console.profile('MyProfile'); // Run some code that you want to measure the performance of for (let i = 0; i < 100000; i++) { // Do something } console.profileEnd('MyProfile'); ``` 這將開始分析 `console.profile` 和 `console.profileEnd` 呼叫之間的程式碼,並在執行 `console.profileEnd` 時在控制台中輸出結果。輸出將包括有關執行所花費時間的詳細訊息、以及其他與性能相關的各種訊息。 ![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjw25tagjwdupmqxy1d5.png) ## 💭 最後的一些想法 在 2023 年,不要僅僅滿足於 `console.log` - JavaScript 控制台物件中有許多**更強大、更有價值的工具和技術。** 從 `console.table` 到 `console.time`,這些方法和技巧將幫助您提高除錯輸出的品質和可讀性,並使其**更容易排除和修復代碼中的問題**。 所以,為什麼不在 2023 年提高您的除錯技能並嘗試這些技術呢? 以上簡單分享,希望對您有幫助!

如何在 React 中漂亮地 render 一個列表:四點注意事項

面試的時候,常常會被問到這題。看似簡單,其實有一些進階注意事項,此篇與您分享。 - 原文出處:https://dev.to/andyrewlee/stand-out-in-a-react-interview-by-rendering-a-list-like-a-pro-1cn5 # 基本做法 以下是最基本做法。根據陣列內容,直接渲染成一個列表。 ``` import { useState, useEffect } from "react"; const App = () => { const [posts, setPosts] = useState([]); const [currentPost, setCurrentPost] = useState(undefined); useEffect(() => { const initialize = async () => { const res = await fetch("https://jsonplaceholder.typicode.com/posts"); const json = await res.json(); setPosts(json); }; initialize(); }, []); const onPostClick = (post) => { setCurrentPost(post); }; return ( <div> {currentPost && <h1>{currentPost.title}</h1>} <PostList posts={posts} onPostClick={onPostClick} /> </div> ); }; const PostList = ({ posts, onPostClick }) => { return ( <div> {posts.map((post) => ( <Post post={post} onPostClick={onPostClick} /> ))} </div> ); }; const Post = ({ post, onPostClick }) => { const onClick = () => { onPostClick(post); }; return <div onClick={onClick}>{post.title}</div>; }; export default App; ``` # 改進方法 以下是四個可以改進的方向,以及背後的原因。 ## 1. 指定 key 替每個元件提供一個 key 屬性,可以幫助後續 React 渲染時改善效能。要注意 key 屬性要是唯一值,不要直接用陣列索引當成 key。 ``` {posts.map((post) => ( <Post key={post.id} post={post} onPostClick={onPostClick} /> ))} ``` ## 2. 優化渲染 每次點擊列表項目時,都會重新渲染 `PostList` 和每個 `Post`。 ``` const Post = ({ post, onPostClick }) => { console.log("post rendered"); const onClick = () => { onPostClick(post); }; return <div onClick={onClick}>{post}</div>; }; ``` 可以使用 React 提供的 `memo` 功能來優化 `PostList` 元件。用 `memo` 包裝元件時,等於告訴 React:除非 props 改變,否則不要重新渲染這個元件。 ``` import { useState, useEffect, memo } from "react"; const PostList = memo(({ posts, onPostClick }) => { return ( <div> {posts.map((post) => ( <Post post={post} onPostClick={onPostClick} /> ))} </div> ); }); ``` 不過,實際跑下去,會發現還是重新渲染了。因為每次 currentPost 改變時,App 都會重新渲染。每次重新渲染都會重新建立 onPostClick 函數。當一個函數被重新建立時(即使函式內容一樣),都算是新的實體。所以技術上來說,props 確實發生了變化,所以 `PostList` 會重新渲染。 ``` const fn1 = () => {}; const fn2 = () => {}; fn1 === fn2; // => false ``` 這種狀況,就可以使用 useCallback hook 來告訴 React 不要重新建立函數。 ``` const onPostClick = useCallback((post) => { setCurrentPost(post); }, []); ``` 上面的例子中,使用 useCallback 沒問題,可以避免全部貼文被重新渲染。但要知道的是,並非什麼函式都適合包在 useCallback 裡面。 ``` const Post = ({ post, onPostClick }) => { const useCalllback(onClick = () => { onPostClick(post); }, []); return <div onClick={onClick}>{post.title}</div>; }; ``` 比方說,在 Post 元件使用 useCallback 就不太有意義。因為這個元件是輕量級的。應該只在有意義的情況下使用 useCallback(可以用 profiling 工具分析效能確認)。`useCallback` 有缺點:它增加了程式碼的複雜性。使用 useCallback 會在每次渲染時運行的額外程式碼。 ## 3. 元件卸載時清理乾淨 目前的元件沒有在卸載時進行清理。例如,如果在收到 URL 回應結果之前就離開頁面怎麼辦?這時應該要取消請求。 ``` useEffect(() => { const initialize = async () => { const res = await fetch("https://jsonplaceholder.typicode.com/posts"); const json = await res.json(); setPosts(json); }; initialize(); }, []); ``` `useEffect` 可以分為兩部分:掛載時運行的程式碼、卸載時運行的程式碼: ``` useEffect(() => { // When component mounts what code should I run? return () => { // When component unmounts what code should I run (clean up)? }; }, []); ``` 我們可以使用 AbortController ,並在清理時呼叫 controller.abort() 來取消請求。 ``` useEffect(() => { const controller = new AbortController(); const signal = controller.signal; const initialize = async () => { try { const res = await fetch("https://jsonplaceholder.typicode.com/posts", { signal }); const json = await res.json(); setPosts(json); } catch (err) { console.log(err); } }; initialize(); return () => { controller.abort(); }; }, []); ``` ## 4. 增加無障礙輔助功能 以上範例太過簡單,沒有太多無障礙功能可以加入。一旦應用程式變複雜,絕對應該要開始考慮這點。 有個簡單的無障礙測試:可以單獨只使用鍵盤就操作一個應用程式嗎? 關於這點,快速解法是:把每個項目都轉成按鈕,用鍵盤時就可以在元件之間切換。 ``` const Post = ({ post, onPostClick }) => { const onClick = () => { onPostClick(post); }; return <button onClick={onClick}>{post}</button>; }; ``` # 結論 在 React 中渲染列表,乍看之下,只是個簡單的面試問題。但其實可深可淺。下次面試時遇到這問題,可以思考一下此篇文章談到的各個面向。

開發 React 時,推薦使用這些 Best Practices

在開發 React App 時,遵循一些 best practices 會使您的程式碼品質提高,這篇文章列出一些給您參考。 - 原文出處:https://dev.to/iambilalriaz/react-best-practices-ege # 強烈推薦 VS Code 作為 IDE Visual Studio Code 有幾個超好用的 React 功能。強大的外掛生態系,對開發者大有幫助: - Prettier - ES Lint - JavaScript (ES6) code snippets - Reactjs code snippets - Auto import # 使用 ES6 語法 程式碼越漂亮越好。在 JavaScript 中,採用 ES6 語法可以讓程式碼更簡潔。 ## Arrow Functions ``` // ES5 function getSum(a, b) { return a + b; } // ES6 const getSum = (a, b) => a + b; ``` ## Template Literal ``` // ES5 var name = "Bilal"; console.log("My name is " + name); // ES6 const name = "Bilal"; console.log(`My name is ${name}`); ``` ## const $ let const $ let 有各自的變數作用域。const 宣告的變數不能修改,let 宣告的變數可以修改。 ``` // ES5 var fruits = ["apple", "banana"]; // ES6 let fruits = ["apple", "banana"]; fruits.push("mango"); const workingHours = 8; ``` ## Object Destructuring ``` var person = { name: "John", age: 40, }; // ES5 var name = person.name; var age = person.age; // ES6 const { name, age } = person; ``` ## Defining Objects ``` var name = "John"; var age = 40; var designations = "Full Stack Developer"; var workingHours = 8; // ES5 var person = { name: name, age: age, designation: designation, workingHours: workingHours, }; // ES6 const person = { name, age, designation, workingHours }; ``` ES6 的語法特性、彈性,很多值得您一試。 # JSX 使用 map 時記得加上 key array map 時,永遠記得替每個元素加上獨立的 key 值。 ``` const students = [{id: 1, name: 'Bilal'}, {id: 2, name: 'Haris'}]; // in return function of component <ul> {students.map(({id, name}) => ( <li key={id}>{name}</li> ))} </ul>; ``` # 元件名稱使用 PascalCase ``` const helloText = () => <div>Hello</div>; // wrong const HelloText = () => <div>Hello</div>; // correct ``` # 變數和函數名稱使用 camelCase ``` const working_hours = 10; // bad approach const workingHours = 10; // good approach const get_sum = (a, b) => a + b; // bad approach const getSum = (a, b) => a + b; // good approach ``` # ID 和 css class 名稱使用 kebab-case ``` <!--bad approach--> <div className="hello_word" id="hello_world">Hello World</div> <!--good approach --> <div className="hello-word" id="hello-world">Hello World</div> ``` # 永遠要檢查物件&陣列的 null & undefined 忘記檢查的話,常常會導致一堆錯誤。 所以要保持檢查的習慣。 ``` const person = { name: "Haris", city: "Lahore", }; console.log("Age", person.age); // error console.log("Age", person.age ? person.age : 20); // correct console.log("Age", person.age ?? 20); //correct const oddNumbers = undefined; console.log(oddNumbers.length); // error console.log(oddNumbers.length ? oddNumbers.length : "Array is undefined"); // correct console.log(oddNumbers.length ?? "Array is undefined"); // correct ``` # 避免 Inline Styling Inline styling 會讓 jsx 程式碼變得很亂。用單獨的 css 文件拆分出來比較好。 ``` const text = <div style={{ fontWeight: "bold" }}>Happy Learing!</div>; // bad approach const text = <div className="learning-text">Happy Learing!</div>; // good approach ``` 在 .css 文件中: ``` .learning-text { font-weight: bold; } ``` # 避免 DOM 操作 用 React state 為主,別用 DOM 操作 糟糕做法: ``` <div id="error-msg">Please enter a valid value</div> ``` ``` document.getElementById("error-msg").visibility = visible; ``` 推薦做法: ``` const [isValid, setIsValid] = useState(false); <div hidden={isValid}>Please enter a valid value</div>; ``` 使用 isValid 來管理 UI 顯示邏輯。 # 在 useEffect 記得清乾淨每個事件監聽器 加過的事件監聽器,都要記得清乾淨: ``` const printHello = () => console.log("HELLO"); useEffect(() => { document.addEventListener("click", printHello); return () => document.removeEventListener("click", printHello); }); ``` # 避免重複開發,多寫通用元件 讓程式碼越乾淨越好。相似的東西可以寫通用元件。再根據 props 內容傳遞來處理相異處即可: ``` const Input=(props)=>{ const [inputValue, setInputValue]=useState(''); return( <label>{props.thing}</label> <input type='text' value={inputValue} onChange={(e)=>setInputValue(e.target.value)} /> ) } ``` 在其他元件中,就能這樣用: ``` <div> <Input thing="First Name" /> <Input thing="Second Name" /> </div> ``` # 檔案要分類一下 相關檔案可以分類成一個資料夾。 例如在 React 寫一個導覽列,那就可以開一個資料夾,相關的 .js 與 .css 檔案放裡面。 # 寫 functional components 為主 簡單顯示一些東西、沒用到 state 的話,那寫 functional components 比寫 class components 好。 如果你會寫 react hooks 的話,那就連 state 都完全不成問題。 # 養成編寫輔助函數的習慣 有時你在 React App 中會需要一些通用功能。 這種情況,可以開一個 `helper-functions.js` 檔案,在裡面寫輔助函數,就可以到處使用了。 ## 使用三元運算子代替 if/else if 使用 `if/else if` 語句會使程式碼變得龐大。使用三元運算子,就簡潔、清楚多了: ``` // Bad approach if (name === "Ali") { return 1; } else if (name === "Bilal") { return 2; } else { return 3; } // Good approach name === "Ali" ? 1 : name === "Bilal" ? 2 : 3; ``` # 新增 index.js 檔案,讓匯入元件更簡單 如果你在 actions 資料夾中有一個 index.js 檔案,當你想在元件中導入時,會像這樣: ``` import { actionName } from "src/redux/actions"; ``` actions 後面的 index.js 可以省略不寫,就不用這樣囉唆了: ``` import { actionName } from "src/redux/actions/index"; ``` # Destructuring of Props 物件屬性名稱可以拆出來,後面用起來比較方便。 假設你的元件有 `name`、`age` 和 `designation` 這些 props: ``` // Bad approach const Details = (props) => { return ( <div> <p>{props.name}</p> <p>{props.age}</p> <p>{props.designation}</p> </div> ); }; // Good approach const Details = ({ name, age, designation }) => { return ( <div> <p>{name}</p> <p>{age}</p> <p>{designation}</p> </div> ); }; ``` # 不要嘗試在同一函數中,去碰修改過的 state 變數 在一個函數中,如果你正在為一個狀態變數賦值,在同一個函數中,是拿不到新值的 ``` const Message = () => { const [message, setMessage] = useState("Hello World"); const changeMessage = (messageText) => { setMessage("Happy Learning"); console.log(message); // It will print Hello World on console }; return <div>{message}</div>; }; ``` # 使用 === 運算子代替 == 在比較兩個值時,嚴格檢查變數型別比較好: ``` "2" == 2 ? true : false; // true "2" === 2 ? true : false; // false ``` --- 以上 Best Practices 供您參考,祝福您不斷變強!

給工程師的12個超好用API、可串接大量有趣資料~!

不管是寫程式的新手、老手,在做專案的時候,常常需要資料,來讓專案內容更豐富吧! 這時候需要去找有趣、夠酷、免費的 API 來用! 這篇文章一次整理出 12 個有豐富資料的有趣 API!有空要用用看喔! - 原文出處:https://dev.to/monicafidalgo/12-apis-that-you-as-a-developer-will-love-it-4ec6 # ✨1. PokéAPI 來串寶可夢精靈 API 吧!可以撈到大量神奇寶貝資訊(動作、類型、能力)! - https://pokeapi.co/ - 需要 API 密鑰:否 # ✨2. GIPHY GIPHY 是世界上最大的 GIF 資料庫,可以撈到一大堆梗圖,方便你開發有趣的 side project! - https://developers.giphy.com/ - 需要 API 密鑰:是 # ✨3. Open Weather 串接這個API,馬上得知明天天氣!Open Weather API 收集和處理來自不同來源的天氣數據,例如全球和本地天氣模型、衛星、雷達、各種氣象站資訊! - https://openweathermap.org/api - 需要 API 密鑰:否 # ✨4. {JSON} Placeholder 快速撈一些 json 假資料,方便開發時有資料可以快速測試! - https://jsonplaceholder.typicode.com/ - 需要 API 密鑰:否 # ✨5. SWAPI 電影「星際大戰」API,擁有大量行星、宇宙飛船、車輛、電影和物種的數據~! - https://swapi.dev/ - 需要 API 密鑰:否 # ✨6. NASA NASA 就是美國國家航空暨太空總署,提供大量來自 NASA 的真實數據,包括 NASA 好奇號、機遇號和精神號探測器在火星上收集的圖像數據! - https://api.nasa.gov/ - 需要 API 密鑰:是 # ✨7. Unsplash 由大量攝影師上傳照片的優質圖片資料庫!開發網站首頁、串接漂亮照片的必備 API 網站! - https://unsplash.com/developers - 需要 API 密鑰:是 # ✨8. Dev.to dev.to 是國外一個開發者討論區,在上面寫文章的話,可以透過 API 把文章撈出來! - https://developers.forem.com/api - 需要 API 密鑰:否 # ✨9. Breaking Bad Netflix 神劇,《絕命毒師》的的 API。它可以讓你拿到劇中名言、人物、集數、各式死亡資訊! - https://breakingbadapi.com/documentation - 需要 API 密鑰:否 # ✨10. Random Data 想發揮創意並在專案中使用各種奇怪資料嗎?也許是一款隨機獲得啤酒或電腦的遊戲?試試看隨機資料 API 吧~! - https://random-data-api.com/documentation - 需要 API 密鑰:否 # ✨11. Rest Countries Rest Countries 讓您可以通過 RESTful API 拿到有關各個國家/地區的大量豐富資訊~! - https://restcountries.com/#rest-countries - 需要 API 密鑰:否 # ✨12. Rick and Morty Rick and Morty 系列很受工程師歡迎!這個 API 可以讓你按劇集、角色、地點進行查詢~! - https://rickandmortyapi.com/documentation - 需要 API 密鑰:否