🔍 搜尋結果:研究

🔍 搜尋結果:研究

如何在微前端 Micro Frontends 架構中處理 CSS

如何在微前端中處理 CSS?畢竟,樣式始終是*任何* UI 片段所需要的東西,但是,它也是全局共享的東西,因此是潛在的衝突來源。 在這篇文章中,我想回顧一下現有的不同策略來馴服 CSS 並使其擴展以開發微前端。如果這裡的任何內容對您來說聽起來很合理,那麼也可以考慮研究一下[“微前端的藝術”](https://microfrontends.art/)。 **本文的程式碼可以在[github.com/piral-samples/css-in-mf](https://github.com/piral-samples/css-in-mf)找到。請務必查看示例實現。** CSS 的處理是否會影響每個微前端解決方案?讓我們檢查可用的類型來驗證這一點。 原文出處:https://dev.to/florianrappl/css-in-micro-frontends-4jai ## 微前端的類型 過去我寫了很多關於存在哪些類型的微前端、為什麼存在以及何時應該使用什麼類型的微前端架構的文章。採用 Web 方法意味著使用 iframe 來使用來自不同微前端的 UI 片段。在這種情況下,沒有任何限制,因為無論如何每個片段都是完全隔離的。 在任何其他情況下,無論您的解決方案使用客戶端還是伺服器端組合(或介於兩者之間的東西),您最終都會得到在瀏覽器中評估的樣式。因此,在所有其他情況下,您都會關心 CSS。讓我們看看這裡有哪些選項。 ## 無特殊處理 好吧,第一個 - 也許是最(或根據觀點,最不)明顯的解決方案是不進行任何特殊處理。相反,每個微前端都可以附帶額外的樣式表,然後在渲染微前端的元件時附加這些樣式表。 理想情況下,每個元件僅在首次渲染時加載所需的樣式,但是,由於這些樣式中的任何一個都可能與現有樣式衝突,我們也可以假裝在微前端的任何元件渲染時加載所有“有問題的”樣式。 ![衝突](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fewl99l6y04edyjnni2j.png) 這種方法的問題在於,當給出諸如“div”或“div a”之類的通用選擇器時,我們還將重新設置其他元素的樣式,而不僅僅是原始微前端的片段。更糟糕的是,類和屬性也不是故障保護措施。像“.foobar”這樣的類也可以在另一個微前端中使用。 **您將在引用的演示存儲庫中找到兩個衝突的微前端的示例,網址為 [solutions/default](https://github.com/piral-samples/css-in-mf/tree/main/solutions)。** 擺脫這種痛苦的一個好方法是進一步隔離元件 - 就像 Web 元件一樣。 ## 影子 DOM 在自定義元素中,我們可以打開一個影子根來將元素附加到專用的迷你文件,該迷你文件實際上與其父文件屏蔽。總的來說,這聽起來是一個好主意,但與這裡介紹的所有其他解決方案一樣,沒有硬性要求。 ![Shadow DOM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xp18uw9sxffq1l7oj6mc.png) 理想情況下,微前端可以自由決定“如何”實現元件。因此,實際的 Shadow DOM 集成必須由微前端完成。 使用 Shadow DOM 有一些缺點。最重要的是,雖然 Shadow DOM 內部的樣式保留在內部,但全局樣式也不會影響 Shadow DOM。乍一看,這似乎是一個優勢,但是,由於整篇文章的主要目標只是隔離微前端的樣式,因此您可能會錯過諸如應用某些全局設計系統(例如 Bootstrap)之類的要求。 要使用 Shadow DOM 進行樣式設置,我們可以通過“link”引用或“style”標籤將樣式放入 Shadow DOM 中。由於 Shadow DOM 是無樣式的,並且外部的樣式不會傳播到其中,因此我們實際上需要它。除了編寫一些內聯樣式之外,我們還可以使用捆綁器將“.css”(或者類似“.shadow.css”的內容)視為原始文本。這樣,我們只會得到一些文本。 對於 esbuild,我們可以配置 `piral-cli-esbuild` 的預製配置,如下所示: ``` module.exports = function(options) { options.loader['.css'] = 'text'; options.plugins.splice(0, 1); return options; }; ``` 這會刪除初始 CSS 處理器 (SASS) 並為“.css”文件配置標準加載器。現在,shadow DOM 中的某些樣式的工作方式如下: ``` import css from "./style.css"; customElements.define(name, class extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } connectedCallback() { this.style.display = "contents"; const style = this.shadowRoot.appendChild(document.createElement('style')); style.textContent = css; } }); ``` 上面的程式碼是一個有效的自定義元素,從樣式角度來看它是透明的(“display:contents”),即只有其內容會反映在渲染樹中。它託管一個包含單個“style”元素的影子 DOM。 `style` 的內容設置為 `style.css` 文件的文本。 **您將在 [`solutions/shadow-dom`](https://github.com/piral-samples/css-in-mf/tree/main) 引用的演示存儲庫中找到兩個衝突的微前端的示例/解決方案/shadow-dom)。** 域元件避免使用影子 DOM 的另一個原因是,並非每個 UI 框架都能夠處理影子 DOM 中的元素。因此,無論如何都必須尋找替代解決方案。一種方法是轉而使用一些 CSS 約定。 ## 使用命名約定 如果每個微前端都遵循全局 CSS 約定,那麼就可以在元級別上避免衝突。最簡單的約定是在每個類前面加上微前端的名稱。因此,舉例來說,如果一個微前端稱為“shopping”,另一個微前端稱為“checkout”,那麼兩者都會將其“active”類分別重命名為“shopping-active”/“checkout-active”。 ![約定](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6l8r1s59v1dcu3yp022u.png) 這同樣適用於其他可能存在衝突的名稱。舉個例子,在微前端稱為“shopping”的情況下,我們將其稱為“shopping-primary-button”,而不是像“primary-button”這樣的ID。如果由於某種原因,我們需要設置元素的樣式,我們應該使用後代選擇器(例如“.shopping img”)來設置“img”標籤的樣式。現在,這適用於具有“shopping”類的 *some* 元素中的“img”元素。這種方法的問題是購物微前端也可能使用其他微前端的元素。如果我們看到“div.shopping > div.checkout img”怎麼辦?儘管“img”現在由通過“checkout”微前端帶來的元件託管/集成,但它的樣式將由“shopping”微前端 CSS 設計。這並不理想。 儘管命名約定在一定程度上解決了問題,但它們仍然容易出錯並且使用起來很麻煩。如果我們重命名微前端會怎樣?如果微前端在不同的應用程式中獲得不同的名稱怎麼辦?如果我們在某些時候忘記應用命名約定怎麼辦?這就是工具幫助我們的地方。 ## CSS 模塊 自動引入一些前綴並避免命名衝突的最簡單方法之一是使用 CSS 模塊。根據您選擇的捆綁器,這可以是開箱即用的,也可以通過一些配置更改來實現。 ![CSS 模塊](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o49rdmokn5kvn8ncjjrt.png) ``` // Import "default export" from CSS import styles from './style.modules.css'; // Apply <div className={styles.active}>Active</div> ``` 導入的模塊是一個生成的模塊,保存將其原始類名(例如“active”)映射到生成的類名的值。生成的類名通常是 CSS 規則內容與原始類名混合的哈希值。這樣,名稱應該盡可能唯一。 作為示例,讓我們考慮使用“esbuild”建置的微前端。對於“esbuild”,您需要一個插件(“esbuild-css-modules-plugin”)和相應的配置更改以包含 CSS 模塊。 使用 Piral 我們只需要調整 `piral-cli-esbuild` 已經帶來的配置。我們刪除標準 CSS 處理(使用 SASS)並用插件替換: ``` const cssModulesPlugin = require('esbuild-css-modules-plugin'); module.exports = function(options) { options.plugins.splice(0, 1, cssModulesPlugin()); return options; }; ``` 現在我們可以在程式碼中使用 CSS 模塊,如上所示。 CSS 模塊有一些缺點。首先,它附帶了一些標準 CSS 的語法擴展。這對於區分我們想要導入的樣式(因此要進行預處理/哈希)和應保持原樣的樣式(即稍後在不導入的情況下使用)是必要的。另一種方法是將CSS直接帶入JS文件中。 ## CSS-in-JS CSS-in-JS 最近的名聲很差,但是,我認為這是一個誤解。我也更喜歡將其稱為“CSS-in-Components”,因為它為元件本身帶來了樣式。一些框架(Astro、Svelte 等)甚至允許通過其他方式直接執行此操作。經常被提及的缺點是性能 - 這通常是由於在瀏覽器中編寫 CSS 造成的。然而,這並不總是必要的,在最好的情況下,CSS-in-JS 庫實際上是建置時間驅動的,即沒有任何性能缺陷。 ![CSS-in-JS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36w7yuksmdzgstastjxv.png) 然而,當我們談論 CSS-in-JS(或 CSS-in-Components)時,我們需要考慮現有的各種選項。為簡單起見,我只包含三個:情感、樣式元件和香草提取物。讓我們看看它們如何幫助我們在將微前端整合到一個應用程式中時避免衝突。 ### Emotion Emotion 是一個非常酷的庫,它附帶了 React 等框架的幫助程序,但沒有將這些框架設置為先決條件。情感可以很好地優化和預先計算,並允許我們使用可用的 CSS 技術的完整庫。 使用“純粹”情感相當容易;首先安裝包: ``` npm i @emotion/css ``` 現在您可以在程式碼中使用它,如下所示: ``` import { css } from '@emotion/css'; const tile = css` background: blue; color: yellow; flex: 1; display: flex; justify-content: center; align-items: center; `; // later <div className={tile}>Hello from Blue!</div> ``` `css` 幫助器允許我們編寫被解析並放置在樣式表中的 CSS。返回值是生成的類的名稱。 如果我們特別想使用 React,我們還可以使用 Emotion 中的 jsx 工廠(引入了一個名為 css 的新標準 prop)或 styled 幫助器: ``` npm i @emotion/react @emotion/styled ``` 現在感覺很像樣式是 React 本身的一部分。例如,“styled”幫助器允許我們定義新元件: ``` const Output = styled.output` border: 1px dashed red; padding: 1rem; font-weight: bold; `; // later <Output>I am groot (from red)</Output> ``` 相比之下,“css”輔助屬性使我們能夠稍微縮短符號: ``` <div css={` background: red; color: white; flex: 1; display: flex; justify-content: center; align-items: center; `}> Hello from Red! </div> ``` 總而言之,這會生成不會衝突的類名,並提供避免樣式混合的穩健性。 “styled”助手尤其受到流行的“styled-components”庫的啟發。 ### 樣式元件 “styled-components”庫可以說是最流行的 CSS-in-JS 解決方案,並且常常是此類解決方案聲譽不佳的原因。從歷史上看,這實際上是在瀏覽器中編寫 CSS 的全部內容,但在過去幾年中,他們確實極大地推進了這一點。今天,您也可以對所使用的樣式進行一些非常好的伺服器端組合。 與“emotion”相比,安裝(針對 React)需要更少的軟體包。唯一的缺點是打字是事後才想到的 - 所以你需要安裝兩個包才能完全喜歡 TypeScript: ``` npm i styled-components --save npm i @types/styled-components --save-dev ``` 安裝後,該庫就已經完全可用: ``` import styled from 'styled-components'; const Tile = styled.div` background: blue; color: yellow; flex: 1; display: flex; justify-content: center; align-items: center; `; // later <Tile>Hello from Blue!</Tile> ``` 其原理與“情感”相同。因此,讓我們探索另一種選擇,嘗試從一開始就實現零成本,而不是事後的想法。 ### Vanilla Extract 我之前寫的關於利用類型更接近元件(並避免不必要的執行時成本)的內容正是最新一代 CSS-in-JS 庫所涵蓋的內容。最有前途的庫之一是“@vanilla-extract/css”。 使用該庫有兩種主要方式: - 與您的捆綁器/框架集成 - 直接使用 CLI 在此示例中,我們選擇前者 - 並將其集成到“esbuild”。為了使集成正常工作,我們需要使用“@vanilla-extract/esbuild-plugin”包。 現在我們將其集成到建置過程中。使用 `piral-cli-esbuild` 配置,我們只需將其加入到配置的插件中: ``` const { vanillaExtractPlugin } = require("@vanilla-extract/esbuild-plugin"); module.exports = function (options) { options.plugins.push(vanillaExtractPlugin()); return options; }; ``` 為了使 Vanilla Extract 正常工作,我們需要編寫 `.css.ts` 文件,而不是普通的 `.css` 或 `.sass` 文件。這樣的文件可能如下所示: ``` import { style } from "@vanilla-extract/css"; export const heading = style({ color: "blue", }); ``` 這都是有效的 TypeScript。我們最終會得到一個類名的導出 - 就像我們從 CSS 模塊、Emotion 中得到的一樣 - 你明白了。 所以最後,上面的樣式將像這樣應用: ``` import { heading } from "./Page.css.ts"; // later <h2 className={heading}>Blue Title (should be blue)</h2> ``` 這將在建置時完全處理——而不是執行時成本。 您可能會感興趣的另一種方法是使用 CSS 實用程序庫,例如 Tailwind。 ## CSS 實用程序,例如 Tailwind 這是一個獨立的類別,但我認為既然 Tailwind 是這個類別中的主要工具,我將只介紹 Tailwind。 Tailwind 的主導地位甚至達到了甚至有人問“你寫 CSS 還是 Tailwind?”之類的問題。這與 jQuery 在 DOM 操作領域的統治地位非常相似。 2010 年,人們問“這是 JavaScript 還是 jQuery?”。 無論如何,使用 CSS 實用程序庫的優點是根據使用情況生成樣式。這些樣式不會衝突,因為實用程序庫始終以相同的方式定義它們。因此,每個微前端將僅附帶實用程序庫中根據需要顯示微前端所需的部分。 ![Tailwind](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8waj7k3823oq77qhkzmb.png) 如果使用 Tailwind 和 esbuild,我們還需要安裝以下軟體包: ``` npm i autoprefixer tailwindcss esbuild-style-plugin ``` esbuild的配置比之前複雜一點。 `esbuild-style-plugin` 本質上是 esbuild 的 PostCSS 插件;所以必須正確配置: ``` const postCssPlugin = require("esbuild-style-plugin"); module.exports = function (options) { const postCss = postCssPlugin({ postcss: { plugins: [require("tailwindcss"), require("autoprefixer")], }, }); options.plugins.splice(0, 1, postCss); return options; }; ``` 在這裡,我們刪除了默認的 CSS 處理插件 (SASS),並將其替換為 PostCSS 插件 - 使用 PostCSS 的“autoprefixer”和“tailwindcss”擴展。 現在我們需要加入一個有效的 *tailwind.config.js* 文件: ``` module.exports = { content: ["./src/**/*.tsx"], theme: { extend: {}, }, plugins: [], }; ``` 這本質上是配置 Tailwind 的最低要求。它只是提到應該掃描 `tsx` 文件以了解 Tailwind 實用程序類的使用情況。然後找到的類將被放入 CSS 文件中。 因此,CSS 文件還需要知道生成/使用的聲明應包含在哪裡。至少我們只有以下 CSS: ``` @tailwind utilities; ``` 還有其他“@tailwind”指令。例如,Tailwind 帶有重置和基礎層。然而,在微前端中,我們通常不關心這些層。這屬於應用程式 shell 或編排應用程式的關注範圍 - 而不是域應用程式。 然後,CSS 將被替換為 Tailwind 中已指定的類: ``` <div className="bg-red-600 text-white flex flex-1 justify-center items-center">Hello from Red!</div> ``` ## 比較 迄今為止提出的幾乎每種方法都是微前端的可行競爭者。一般來說,這些溶液也可以混合。一個微前端可以採用影子 DOM 方法,而另一個微前端則對 Emotion 感到滿意。第三個圖書館可能會選擇使用香草精。 最後,唯一重要的是所選擇的解決方案是無碰撞的,並且不會帶來(巨大的)執行時成本。雖然某些方法比其他方法更有效,但它們都提供了所需的樣式隔離。 |方法|遷移工作|可讀性|穩健性|性能影響| | ----------- | -------------- | -------------- | ---------- | ------------------ | |大會 |中等|高|低|無 | | CSS 模塊 |低|高|中等|從無到低| |影子 DOM |低到中|高|高|低| | JS 中的 CSS |高|中到高|高|從無到高| |順風|高|中等|高|無 | 性能影響很大程度上取決於實施。例如,對於 CSS-in-JS,如果解析和組合在執行時完全完成,您可能會產生很大的影響。如果樣式已經預先解析但僅在執行時組合,則影響可能很小。如果使用像香草精這樣的解決方案,您基本上不會產生任何影響。 對於 Shadow DOM,主要的性能影響可能是 Shadow DOM 內部元素的投影或移動(本質上為零)以及“style”標籤的重新評估。然而,這是相當低的,甚至可能會產生一些性能優勢,給定的樣式總是切中要害,並且僅專用於要在影子 DOM 中顯示的某個元件。 在示例中,我們有以下捆綁包大小: |方法|索引 [kB] |頁碼 [kB] |表 [kB] |總體 [kB] |尺寸 [%] | | ----------------- | ---------- | --------- | ----------- | ------------ | ------ | |默認| 1.719 | 1.719 1.203 | 1.203 0.245 | 0.245 3.167 | 3.167 100% | |大會 | 1.761 | 1.761 1.241 | 1.241 0.269 | 0.269 3.271 | 3.271 103% | | CSS 模塊 | 2.149 | 2.149 2.394 | 2.394 0 | 4.543 | 4.543 143% | |影子 DOM | 10.044 | 10.044 1.264 | 1.264 0 | 11.308 | 11.308 357% | |情感| 1.670 | 1.670 1.632 | 1.632 25.785 | 25.785 29.087 | 29.087 918% | |樣式元件 | 1.618 | 1.618 1.612 | 1.612 63.073 | 63.073 66.303 | 66.303 2093% | |香草精 | 1.800 | 1.800 1.257 | 1.257 0.314 | 0.314 3.371 | 3.371 106% | |順風| 1.853 | 1.853 1.247 | 1.247 0.714 | 0.714 3.814 | 3.814 120% | 對這些數字持保留態度,因為在情感和样式元件的情況下,執行時可以(並且可能甚至應該)共享。另外,給定的示例微前端確實很小(所有 UI 片段的總體大小為 3kB)。對於更大的微前端,增長肯定不會像這裡描述的那麼問題。 Shadow DOM 解決方案的大小增加可以通過我們提供的簡單實用腳本來解釋,該腳本可以輕鬆地將現有的 React 渲染包裝到 Shadow DOM 中(無需生成新樹)。如果這樣的實用程序是集中共享的,那麼其大小將更接近其他更輕量級的解決方案。 ## 結論 在微前端解決方案中處理 CSS 並不困難 - 只需從一開始就以結構化和有序的方式完成,否則就會出現衝突和問題。一般來說,建議選擇 CSS 模塊、Tailwind 或可擴展的 CSS-in-JS 實現等解決方案。

Github 範本專案推薦:學習 React 技術的幾個 Repo

開源對很多事情都非常有用。其中之一是學習新技能。在本文中,我們將介紹 GitHub 上一些最好的開源 React 專案,您可以使用它們來快速提升您的 React 技能。 原文出處:https://dev.to/livecycle/top-github-repositories-to-learn-modern-react-development-5d3h ## 你可以學習的開源 React 專案 ![提升](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/app52pnsi0e6rey24kp1.gif) ## Cal.com ![Cal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2jnra9gxpgh0y04ereq7.png) [https://github.com/calcom/cal.com](https://github.com/calcom/cal.com) Cal.com 將自己標榜為“絕對適合所有人的日程安排基礎設施”。他們是 Calendly 等預約安排服務的競爭對手。他們同時提供託管和自託管產品。它是一個全棧 Next.js 應用程式,它依賴 tRPC 進行類型安全的客戶端到伺服器通信。該存儲庫具有相當廣泛的 Monorepo 設置(使用 Turborepo),可將應用程式拆分為多個包。在樣式方面,Cal.com 使用 TailwindCSS 和無頭 Radix 元件。存儲庫非常活躍,他們積極鼓勵貢獻者。許多問題被標記為“良好的第一期”和“需要幫助”。 ## Taxonomy ![分類法](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfjhtw3tccnosgf5n0rn.png) [https://github.com/shadcn/taxonomy](https://github.com/shadcn/taxonomy) 這個有點不同。它由單個開發人員建置,作為探索新的 Next.js 13 App Router 功能的演示。但是不要讓那個愚弄你。它可以說是使用新 App Router 的最全面的開源應用程式之一。因此,即使對於想要學習如何在生產中使用 App Router 的經驗豐富的 React 開發人員來說,這也是一個很好的資源。 除了用於前端和後端的 Next.js 之外,Taxonomy 使用 NextAuth 進行身份驗證,使用 Prisma 作為 ORM,使用帶有 Radix 的 TailwindCSS 進行樣式設置。特別有趣的是 Stripe 訂閱集成。因此,如果您想了解如何將訂閱集成到您的應用程式中,這就是適合您的存儲庫。 ## Highstorm ![高塔](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40cy6gokdozqqihlqgxr.png) [https://github.com/chronark/highstorm](https://github.com/chronark/highstorm) Highstorm 是這個街區的新玩家。它是一種監視應用程式中發生的事件的服務。您通過他們的 API 提交事件,然後將其輸入 Highstorm 儀表板。再次重申,這是一個基於 Next.js 的專案。它使用 Tinybird 作為分析資料的資料庫,並使用 Clerk 進行身份驗證。如果您想學習如何處理大量分析資料並將它們顯示在精美的圖表中,那麼這個專案很棒。 ## Dub.sh ![配音](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g90d1imz9110lv1uxb5l.png) [https://github.com/steven-tey/dub](https://github.com/steven-tey/dub) Dub.sh 大約在一年前作為開源連結縮短器推出。它是 Bitly 等服務的替代品。它也是基於 Next.js 並結合使用舊頁面和新 App 路由器。它通常是最早採用 Next.js 新功能(例如元資料 API)的專案之一。 該存儲庫是了解多租戶 Next 應用程式的好地方。這些是為不同域下的不同用戶提供服務的應用程式。在 Dub.sh 的情況下,用戶可以加入自己的域以在其下建立縮短的連結。該應用程式的設計也很精美,整個網站上都有許多令人愉悅的動畫。 Framer Motion 庫用於幫助解決此問題。 ## Bulletproof React ![防彈](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1cndmw6tii88v9puz154.png) [https://github.com/alan2207/bulletproof-react](https://github.com/alan2207/bulletproof-react) Bulletproof React 與我們目前介紹的其他專案不同。該存儲庫確實包含一個功能齊全的演示 React 應用程式。但最大的價值來自閱讀此應用程式附帶的綜合文件。本文件列出了設計大型 React 應用程式各個方面的最佳實踐。這是一個很好的資源,可以定期參考以刷新您對最佳實踐的記憶。 ## 總結和開始 正如我們所見,上述每個存儲庫都提供了一個獨特的視角來了解大型 React 應用程式是如何建置的。每個人都可以從研究存儲庫的程式碼中獲益,無論您有多有經驗。 開始從存儲庫中學習的一個很好的實用技巧是提出一個特定的問題。例如,您可能會問“Taxonomy 如何處理 Stripe 訂閱?”之類的問題。然後挖掘程式碼層以找到問題的答案。 最後一點——探索開源存儲庫是提升 React 技能的好方法,但這不是您唯一應該做的事情。將您新獲得的知識應用到您自己的專案中也很重要。這就是您鞏固新技能和保留訊息的方式。 最主要的是享受這個過程,並認識到開源是培養新技能的友好場所,無論您目前的經驗水平如何。

西元 2023 年了,還值得花時間學 Dreamweaver 嗎?簡單分享幾個觀點

首先我們來看 google trend ![](https://i.imgur.com/GwTUmvo.png) https://trends.google.com.tw/trends/explore?date=all&geo=TW&q=dreamweaver&hl=zh-TW 如你所見 這是一個過時的技術、正在被人們拋棄 接著請到 google 搜尋 `dreamweaver 職缺` 會發現其實 還是有些職缺要求要會 dreamweaver 這些職缺的待遇、工作內容 都在各大人力資源網站 你可以自行判斷:這些是不是你求職的目標職缺、理想職缺 --- 再來是我個人經驗,我這十年職場所見所聞,沒有遇過公司在用 Dreamweaver 我在社群認識各類工程師,也沒聽過有人在用這工具 不得不說 這實在是一個很老派的工具 唯一有次在業界遇到 好像有人在用的情境 是一間接案公司 以快速、便宜為主打 他們當時需要有人能用低價、快速的方式 把大量網頁切出來 後來找到的配合的人 好像就是用 Dreamweaver 在切版 --- 如果對 Dreamweaver 有興趣、好奇 我覺得多學一個工具 也不是壞事 對於之後再學其它工具 也是會有幫助 但是 應該沒必要花時間「專精」或者「鑽研」這樣一個老舊的工具 如果課程要求 或是有證照需求 那評估一下需要花費的時間 如果證照沒那麼難考 那花點時間 拿個證照 也滿好的 還能培養一些自信 如果履歷表還沒什麼東西能放 那放個證照也不錯 但如果考那證照很花錢、很花時間 那請審慎思考一下這投資值不值得 我是不推薦 我感覺只是培養快速、低成本切版網頁的能力 這能力頂多在接案公司會有幫助 而且還不會是很精緻的接案公司 不如花時間深入研究 JavaScript 基本功,對前端職涯更有幫助,而不只是專精於切版而已 --- 以上 簡單個人觀點分享

後端 JS 訓練一:結語

簡單複習一下,在這次的課程中,我們學會了 - 寫 node 程式 - 讀取、寫入檔案 - 匯入、匯出模組 - 從終端機輸入、輸出訊息 - NPM 套件管理工具 - 非同步語法、同步語法 是不是很有趣呢? --- 補充一點,我在課程中多次提到非同步程式設計很多餘,其實不太精準 拿 node 寫 CLI 當然會覺得非同步程式設計很多餘,那是因為 node 設計的初衷是拿來寫網站後端! 相比於其他像是 php 或 python 語言,js/node 非同步的設計會讓網站後端的效能比較強大! 詳細原因可以先不用知道,有興趣再自己去研究一下即可! --- 再補充一點,隨著 js 與 node 的發展 套件匯入匯出的語法,有時會看到 `require` 的寫法,有時會看到 `import` 的寫法 用 `import` 寫法有一些額外設定&調整要弄 我是為了教學方便,才使用 `require` 的寫法,現在主流都改用 `import` 寫法了! 實務上,就以 `import` 寫法為主吧! 不過,反正就是模組管理而已,你就看情況,隨便哪一種寫法都可以,程式能解決問題最重要! --- 這次的課程內容,完全不需要打開瀏覽器,沒有任何程式是在 `瀏覽器 js 環境` 執行的喔! 都是從 `終端機` 直接要求 `node 主程式` 來執行! --- 坊間的 Node 課程,大多是從「web 後端程式設計」開始教起 雖然也不錯,但是需要一開始就碰 node 的 `http` 模組,或是 `express` 模組 從前端開始認識 javascript 的學習者,常常會在這地方有點「腦袋打結」 分不清 `瀏覽器 js 環境` 以及 `node 環境` 的差別 也分不清為何 `node_modules` 的內容一下是在瀏覽器上出現,一下是在伺服器端出現 所以,我決定退一步來教,我們先學老派的 CLI 應用程式開發 這樣,過程中跟 `網站` `瀏覽器` `web 伺服器` 完全沒關係,你就可以先抓到純粹 node 寫程式的感覺! 古早年代,所有程式都是 CLI 程式,文書處理、作業系統、連電腦遊戲都是 CLI 時至今日,CLI 應用程式看似老派,但依然是開發人員最重要的操作 UI 之一!所以值得學一下! 但我們學一點就好了,不用深入鑽研 CLI 程式的開發技巧,這只是替後面 node 的進階應用、以及後端開發學習鋪路而已! --- 消化、研究完本課程之後,請接著前往下一份教材,繼續邁向資深之路吧! https://codelove.tw/@howtomakeaturn/course/bap2xj

常常懷疑自己該不該繼續走程式設計?簡單分享幾個觀點

不論是在學生、正在轉職、或是剛開始上班 不少人常常有這念頭:我好像不太適合走這條路,怎麼辦? 讓我簡單分享幾個觀點 # 關於天份與熱情 很多人對於社會上各種工作抱有「資格論」的傾象 我抱持相反觀點,我認為你在各行各業,沒有天份、沒有熱情也沒有關係 詳細理由我不贅述,請參考我之前的文章:寫程式不需要天份,也不需要熱情 https://codelove.tw/@howtomakeaturn/post/2anXlx # 我在工作上總是做得很慢 這點跟生產力&考績有直接關係,所以是比較重要沒錯 但是,所謂做得很慢,也可能是公司的要求不合理,或者身處團隊實在太強,同事實在太猛 所以,在職場經常有落後同事的感覺,這比較像一個人與團隊的節奏感的問題 如果你雖不優秀,但主管對你的表現其實尚可接受,你的程式碼 bug 很少、品質也還行,甚至你在各間公司其實也沒真的被開除過,那做得慢一點也還好吧 如果幸運遇到「知道怎麼分配適合任務給你」的專業主管,也許這問題,會更顯得微不足道 # 我還是很經常會懷疑自己 ... 很擔心 ... 有沒有可以參考的大原則、大方向? 有,我建議你留意一件事就好了:「我有沒有在進步」 第一個原因是,寫程式這個行業,日新月異,發展實在太快,開發者需要不斷進步,才能維持競爭力 這種進步可快可慢,有自己的節奏沒關係,但每過幾個月回頭看,要有「我確實有變強一些」的感覺才行 有個很簡單的檢測方法,就是維護自己半年前寫的程式碼時,要有「好垃圾的程式碼,我寫得還真爛」的感覺。這代表你進步很多,否則不就是原地踏步? 第二個原因是,我認識很多所謂學得快、做得也快的工程師,在職業生涯的前幾年,進步非常快 但是,大概在三十歲左右,大家難免速度會慢下來,更希望把重心關注在其他事情,比如生活品味上,這之後的技術能力就進步沒那麼快了 我想說的是,這很像是經典的「龜兔賽跑」的故事,你雖是烏龜,但能走多遠其實也不一定,長久下來未必是落後的,所以關注在自身的進步、成長、學習,準沒錯 # 結論 如果寫程式令你痛苦不堪、同事主管讓你壓力很大、待遇根本遠低預期、一直以來你也根本不覺得自己有在成長進步,那麼是有點慘,或許是該考慮轉行 但如果狀況沒那麼糟,我建議你關注在自己的成長狀態即可 定期寫筆記,記錄自己近期到底學了什麼,通常會發現進步得比想像中得還多 關於程式設計,慢慢研究、慢慢學,或許也能有不錯的發展 --- 以上,簡單看法分享

未來 ChatGPT 會取代軟體工程師嗎?你完全不需要擔心這個

最近看到滿多年輕學生、考慮轉職者提問:未來 ChatGPT 會取代軟體工程師嗎? 看來這個議題已經造成不少 IT 領域學生的焦慮,我非常驚訝,讓我簡單談論一下這件事 # 個人經驗回顧 我在畢業前全心學習 web 前端與後端開發,2012 年畢業時,正逢智慧型手機快速發展,所有公司都在思考如何開發手機 app 來創造新機會,當時媒體的主要論述是:「web 已死!web 工程師都將失業,未來是 mobile app 的世界!」 當時年輕的我,看到這些媒體這樣分析,也是有點焦慮,但同時又有點不服氣,所以依然 100% 心思在研究 web 開發,不管媒體怎麼看衰。現在,10 年過去了,請問 web 職缺消失了嗎? # 媒體的習慣、網紅 YTer 的習慣 想像你住在一個非常小的島嶼國家上,往外走一下就看到海,國家全年365天基本沒什麼大事,每天就是太陽升起、太陽落下。如果你是島上的「新聞從業人員」,請問你每天能做什麼?你當然只能誇大你看到的每件事情。 看到海水漲潮,發新聞:「海水異常上漲!恐有釀禍危機!全國一半人口恐有水災、死亡風險!」 看到海水退潮,發新聞:「近三年最低點!海水不斷消退、國家水資源流失、重大警訊!我國恐成大型沙漠!」 世界上大多數事情本就「帶有波動性」,一下狀況好一下狀況壞,潮起又潮落,正如月有陰晴圓缺,這相當正常。 媒體、網紅,基本上需要吸引人們關注來過活,他總不能每天發新聞:「今天海水正常漲潮,沒什麼特別的。」、「今天海水退潮了,這很自然,不太重要。」 身為現代公民,你要有能力透過媒體吸收新知,但同時也要有能力保持冷靜、自行判斷,不要隨意被影響。你要能看出各種觀點背後相關的利益。 # AI 對職缺的影響 AI 當然對各行各業會有重大衝擊,但是目前也僅止於改善工作效率、優化流程而已。 AI 因為可以加強專業人員的生產力,所以會造成職缺變少一點,但要到「軟體工程師通通失業」、「就靠機器人寫完所有程式」這種程度,實在太誇大了 最後,程式設計已經是各種工作領域之中,最難被機器取代的職缺之一,如果真的被高階人工智能取代,那社會上已經沒有多少工作適合人做,大概會是「無條件基本收入」制度之類的社會 --- # 結論 太廢的技能、感覺問 google 或問 ChatGPT 就有的東西,可以不用學了,像死背課文一樣的任務再也不用做了 除此之外,該學什麼學什麼,不用想太多 上個時代,懂得善用 google 與網際網路的專業人士 vs 不懂得善用的專業人士,生產力有巨大差別 下個時代,懂得善用 AI 的專業人士 vs 不懂得善用的專業人士,生產力有巨大差別 除此之外,跟案主溝通、釐清功能規格、分析各種技術選擇、認識領域知識並設計軟體,是極度複雜的工作,你真的覺得一個機器人放在面前聊天幾分鐘,它就能通通做完給你? --- 以上,簡單看法分享

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` 的內容,上傳到留言區

MVC是一個巨大誤會

我是web工程師,從剛開始學MVC就深感困惑: - 怎麼每個地方說的MVC都不太一樣? - 有些文章講的MVC,跟我正在用的MVC,怎麼像完全不同的東西? Model、Controller、View三者到底如何互動?真是一個定義不明、含糊不清的名詞。 這讓我研究了很久。最後,發覺它是一個嚴重的誤會。 這個誤會導致了學習和溝通上的代價,請聽我娓娓道來。 # 哪些是MVC? web領域,不論前端(client-side)、後端(server-side)、不論什麼程式語言,幾乎所有framework都自稱、或被認為是「MVC」。 有哪些呢? 前端:Backbone.js、AngularJS、Ember.js… 後端:Ruby on Rails、CodeIgniter、Laravel、Django… 真的是這樣嗎?它們全都是MVC嗎? # MVC是什麼? 該怎麼定義MVC呢? 我們先來看看維基百科怎麼說: > MVC模式(Model-View-Controller)是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分:模型(Model)、檢視(View)和控制器(Controller)。 嗯,跟大家說的一樣。我們繼續往下看: > 模型(Model) 用於封裝與應用程式的業務邏輯相關的資料以及對資料的處理方法。「 Model 」有對資料直接存取的權力,例如對資料庫的存取。「Model」不依賴「View」和「Controller」,也就是說, Model 不關心它會被如何顯示或是如何被操作。但是 Model 中資料的變化一般會通過一種重新整理機制被公布。為了實作這種機制,那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在資料 Model 上發生的改變。(比較:觀察者模式(軟體設計模式)) 看起來有些陌生,整段描述跟你的web開發經驗完全不同,對嗎? 最大的疑問來自這句: > 那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在資料 Model 上發生的改變。(比較:觀察者模式(軟體設計模式)) 後面直接叫你去看觀察者模式(observer pattern)。 問題來了:你有在view跟model之間實作observer pattern嗎? 也就是說,你的Model在資料改變之後,能主動通知View嗎? 沒有的話,就根本不符合MVC的定義。 # 全都不是MVC? 我們現在發現MVC有observer pattern這個必要條件了。 事情嚴重了起來。 client-side framework或許能夠符合這個條件。 以Backbone.js官網範例來說,我們可以這樣在Model上註冊: ``` book.on({ "change:title": titleView.update, "change:author": authorPane.update, "destroy": bookView.remove }); ``` 它的確實作了observer pattern。 但server-side framework呢? 你的Model如何能在發生改變之後去「主動通知」View? 你平常開發web哪有用到server push的技術? 所有server-side framework,從Ruby的Rails;PHP的CodeIgniter、Laravel;到Python的Django,他們全都不是MVC。 它們實作的,是昇陽電腦在1998年提出的「Model 2」。 # 什麼是Model 2? Model 2名氣不大,在維基百科連中文條目都沒有。我們看看英文條目怎麼講: > Model 2 is a complex design pattern used in the design of Java Web applications which separates the display of content from the logic used to obtain and manipulate the content. > In a Model 2 application, requests from the client browser are passed to the controller. The controller performs any logic necessary to obtain the correct content for display. 它針對web而設計,讓controller進行必要的程序之後,將資料塞進view去呈現。 正是我們server-side框架在做的事情。 也就是說,server-side目前只能實作Model 2;client-side可以實作Model 2,也可以實作MVC。 # 巨大的代價 web工程師最常碰的就是client-side跟server-side框架。結果整個業界把MVC跟Model 2混為一談,都說成MVC。 這帶來了什麼後果呢? MVC變成一個從初學者到業界工程師,永遠說不清楚、下不了定義的名詞。 這件事對於學習和討論,造成了非常巨大的成本。(參考下方的Q1和Q2) # 那該怎麼辦? 下次有初學者詢問「什麼是MVC」的時候,怎麼回答才不會害他回家之後「越查資料越混亂」? [Rails is not MVC](http://andrzejonsoftware.blogspot.tw/2011/09/rails-is-not-mvc.html)的作者提出了三種解決方法: > 第一個方法是聲稱MVC已經從原始意義改變了,Model 2也可以稱為MVC。如此一來,我們可以用「傳統MVC」或「真MVC」來描述原始的MVC。這是現在普遍的作法,但我不認為改變定義是一個好主意。這幾乎是越搞越亂。 > 第二個方法是到處推廣Rails其實是Model 2,MVC就留給…MVC吧。這很困難,但至少能保持定義不變。 > 第三個是直接忽略這些混亂。管它那麼多? 我個人覺得MVC這個詞已經沒救了,不管怎麼解釋都會帶給別人混亂。 當對方同時學習client-side跟server-side時,混亂更強烈。 我選擇這樣回答: 「MVC有分很多種喔!網路上全部沒寫清楚,你一定看不懂。 沒關係,你只要知道View可以抽出來就好。 C跟M先別管,你先隨便瞎搞吧。」 --- # Q&A ## Q1: 怎麼可能各大server-side framework都搞錯? 確實有人腦袋清醒得很,它就是Python的Django。 Django的官方文件內根本沒有「Controller」這個名詞。 看看Django官網的常見問題: > Q: Django似乎是一個MVC框架,但你們把Controller命名為「View」,把View命名為「Template」。你們幹嘛不用標準命名啊? > A: (前略)…如果你真的很想要一個縮寫,你就說Django是一個MTV框架吧。Model、Template、View。這樣分比較有道理些。 Django不想變成搞亂MVC的幫凶,只好委屈地又發明了一個名詞「MTV」。 ## Q2: 那client-side框架有受影響嗎? 有。client-side框架也必須為MVC巨大誤會浪費一堆時間解釋。 看看Backbone.js官網的常見問答: > Backbone跟「傳統MVC」的關聯何在? > …我們來比較一下Backbone跟像是Rails這種server-side MVC框架的差別… Backbone實作了「傳統MVC」,卻被迫用「傳統MVC」來描述server-side的Model 2,然後花一堆篇幅解釋。 ## Q3: 知道Model 2的存在又如何?我現在依然一片混亂! 沒錯,Model 2跟MVC都用到Model、Controller、View三個名詞,所以看起來類似。 但是,我們不應該再把時間花在思考「MVC怎麼如此難懂」。 我們討論的重點,應該是「如何分辨MVC與Model 2」、「在server-side如何實作Model 2才漂亮」、「在client-side實作MVC跟Model 2的優劣分別何在」。 ## Q4: 好,那你現在回答我,「如何分辨MVC與Model 2」? OK,就讓我拋磚引玉一下。 分別談談Model、View、Controller吧: ### View - Model 2: 不具有行為,只是等別人塞資料進去的模板(template)。 - MVC: 具有監視Model的行為,並以此去改變呈現(presentation)。 兩種View有沒有很像?跟張飛、岳飛一樣像。 看看Backbone.js官網的View範例。你server-side的View哪是長這樣? ``` var DocumentRow = Backbone.View.extend({ tagName: "li", className: "document-row", events: { "click .icon": "open", "click .button.edit": "openEditDialog", "click .button.delete": "destroy" }, initialize: function() { this.listenTo(this.model, "change", this.render); }, render: function() { ... } }); ``` ### Controller - Model 2: 接收請求與參數,轉交給Model處理,再把結果(最新的資料)塞進View。 - MVC: 接收請求與參數,轉交給Model處理。沒其他事了。 兩種Controller有沒有很像?跟小狗、熱狗一樣像。 MVC的View跟Model 2的Controller可能還比較像一點。(隨便說說,千萬別這樣類比。) ### Model - Model 2: 接收Controller傳來的參數,回傳結果。 - MVC: 接收Controller傳來的參數,將結果通知View。 Model倒是有些類似。 總之,Model 2跟MVC除了三個部份的名字一樣之外,沒什麼關聯了。 ## Q5: 我決定徹底鑽研MVC跟Model 2的定義了。給我一些延伸閱讀? http://www.ithome.com.tw/node/77330 http://andrzejonsoftware.blogspot.tw/2011/09/rails-is-not-mvc.html https://docs.djangoproject.com/en/1.7/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names http://backbonejs.org/#FAQ-mvc https://r.je/views-are-not-templates.html --- ##一些社群的看法(2015-2-28) 附上幾個社群的連結,裡面有許多很棒的討論。 https://www.facebook.com/groups/javascript.tw/permalink/600136880087654/ https://www.facebook.com/groups/199493136812961/permalink/759391387489797/ https://www.facebook.com/groups/pythontw/permalink/10153760201638438/ https://www.facebook.com/mosky.liu/posts/10203964969186383 http://www.ithome.com.tw/voice/94877

JavaScript 系列九:發表作業&心得分享

第1課 ── 學習 Vue 元件基本觀念 [作業](https://tinyurl.com/yst8ytys) 第2課 ── 學習 Vue 的 props 觀念 [作業](https://play.vuejs.org/#eNrtF11vFFX0r1w3MW0JM7MYiWRZQCE+YBSJPLo+zO7c7oydvTPeuftRm000lQCWpESMoCFRowIJKU2MMVWqv6azLE/+Bc/9mrl3dtvSiPHFPmznnu9z7vm6a7U30tQd9HGtUWtmHRql7GyLRL00oQy9s3reD7r4MsWDCA/RMk16qFVzPRvOuVu101WuGfKCrkXwSFAGeNnvxwyttQhCnQTYCSYsa6C1iurjhdDxcU4b+MxfXJJ8CFHM+pToE0JpkjGQoY9cdJzQBtgyDCMGNggZ8o/hEbug0e3Y76xY6Nhv45ijLChN+iTAQQUuTeN/bW7qmyO/l8YYvHn/A4UZg/OarodZmATcV4lL+0xxlI6BeWGUuZY4N+1n4eIacl1XILmzaLwkJEtfSZbE2I2T7uIst6aTNsjfoc86YWmHHbwA47SBGO3jwrvQJ0GMqWkmBCrp+PEVllAfLjrD7CLDvcVWrSevjV4GqRAq9NaVdy+5GaMR6UbLq9JArnGpdECHUf+vBPMFWVagEb93U4V102iuxXZIS+r9nFA3DlnDcFBaV97fGakm9WmGFy2Du/uEcmkJnTtXSlCKZ61DZ7RJh2uohMFQYWGKJObp3PSKpgEHkJPGPsNwQqgZRAPUif0sOwOyk2C1VRPwCiYikPoXEsL8iGBa0ACVKL7iiND00cazT3cmt69N129Ovt5+9v3m9MbPJbopJCG2mmIQK2q+VSvUiPNFTgHAgdNLAhwDmAfP1bReqduzle9vy+Sra/nWnRdnS9GQDrZHyDc6nJIsqJRko8lJM7hoE1zRLHhNPFxlB4dJHGAKNODxdHcnv/qTSIb86gPwvKQ2TK2GanJ3O791f3LvRn7v9vTBFzNB0rarrqrjomMX4s5KOxnNRkrRmzbMhKndZywh6PVOHHVWOGPRZSHR8q27k+u3nm5/tvfnRtOTpDpDPUjRedmayoE0N1/DE2fVvGp68F3AK2O0UZyTVIgUBW1GEJh1sdmSTEuUlLJejZBrlXJ+AfElPHxbXq8chjzcPHR6lBnaD+Yu0vNoEgy9XYoxOYTPbMADZ1nwmT0IJcv2XDDTFqGGVmvSzOY3EJruWMRGGVoM2guLWNW3Rajcq5LOJK1VOmbWFd/6q+kZ7RWOGVuN+ecxOU96Pu1GpIHqoj+nfhDAyJLHcYu4vAFrwpEzjAIGM/9U/WVB3YuIE+KoG8LoP1XPBqGABlEG6lYbaDnGI1PMWaR0coTT9rMIBvOJuhDGieyWLkmrwhRzEFHcYVEChkMU+z0iUB/2MwbT1oFlhsFGCDj4xVTg/DjqEgf2uB4oNeBdH9aBExT3lBHVSv2PzKiU6YFWDCln5r/zRMGoVTdeO66rX2/uLzkOH0n5k9+fPtrQyzJHovzq+t6TX//avbm3c3/y5fZk85e9nY38+p3882+n63+0iMhdBJ/5j99NH27lj7+xpysvBAhAlcgee6K05uBhSuSPf2sRXeuThz/ku5stkm+uTz9Zb4SMpVnD8z7q+5lP3QAPPDAZtOmXgCdqx0OOo1Je7xrzHhAp76fFgqh2/itic1PbmLHsW3C15VuwYsc/n8A67ZNikXuOrUdZoFcf4/513TfEVQKyWFTb8PToCqUiBRNabKHKk8L48pmRUBjN7/lB1Ae/dYzPoYWT9XS0gBpoob6g91CpWPWWtTXpMhpDWh3eYKz1T8Y3hooqOkbdVUkKaQyV4mTRx5hDT2loke4REYxtWEBXBEa6AFmejhA8W6IAiTdYKWuodLxWr/Y191Ut3juGBpiyCJZaR5QlBCtJT6Nj3r51Yzxd/y8fu3zKp7c8j/9B1qswP1/Wm3rlSK2WgEVxWD1YxHOLA/7vVx4W89FrRa96s7Uyr1Je+Xfr5OTR62T8N2L3XWg=) 一開始方向錯誤,沒有懂老師出題的用意,就照先前的想法做了控制面板,後來才想清楚不是單純用vue做東西,而是做出quasar這種開發模板用的componen 第3課 ── 學習 Vue 的 events 觀念 [作業](https://play.vuejs.org/#eNrNV1tvG0UU/iuTVVHsNL7kIUJaArQplwgRhIjEC4vU8e7YXrI3ZmedGMtPIaJtIvJAaWkkbiK0qaqmCCGakhT+C/I6zlP+Amdmdta7rhPaChCWsto555uzc8755ptJR7sYBOVWRDRdmwtNagfsFcOz3cCnDC225yPGfA/Vqe8iQytXlIXPMLSXDM/wyKrAWqSOI4ehjuEhZPoQwCMeC3XUGYbpTnOnhRkuFCUQIUpYRD01QijE7QX7bTtkOvpA2dDQzX8BphD69RY8dMSadlgWk0Rw9XNwjTg6rHnRdw0t5zJ9x6fcRYk14mJklV1S7gYlxBsBhPYnREfV8mzOSv3Is3RUx05I8vCPI1grLJJGWYesw1NltmyH4Xw7HzXN7TU8mkCam2M3mqzm8C6dnmEQ0cAZRagUXxyX4kgiwwxHc3+GFHmdme01xuf4FjaXT0vSwnQZZrfPzNH2RufLDGeeKb9/qYOLtIwuehahoT9KtXwr28Rx/JWzEh3T7P8XW8+flmDNebLHudRWmjYbn9vYJj5XZv9EhqX/KsPn2IYfJm9dEG1ldwlr+hbXaOkTMlrwUm1GCDuEsoKhLdiwSHQeefBnaBMThlYUcYZfSAozdjbY89P//HrnZH/rySBKCsZGeTNxnr0S+VzBzGxCXnLEj6OIEShcYnChjDDmpxA38JrMVdLTDwaMuIGDGYERQnOW3UKmg8PwZWilb4HeCDt41NGm1toq1X0KKAcOMOTXh6eZoSnIBUmqEuGsSqDlDNGGSF0QS0HEIOMU5FJOMcg4OblKOURKtwyKM0z5+XvGJYimfGKAXhW0QwnJsmEE+dJAYnQKuiILWoGKwttcJVNnGIas7fDXKdl8F9OG7YGAiQYH2LKg+7AjKHHB0jW8Mm+GxK7YFoOGz1SrLwh0k3DVFIaw1RQmyw7hW21YkUNWhaWBAyGPMiASjtIK5Vb+FDYM8uuVYHe6sE9ChimT3wa+JKvVprXstYhfpCZKJTS4t9F7/MfR9d1476v+jUdH25/G62u9g18Hd28ffX43fvhjvP7w5HD7fSjS0huX0LuwtIYoNC9Fk7Eg1CuVsG7ymB+FZZ82KtzDqwih44Pfju5tpFcrDkIy/snhZm//dv/6g/7WL739jfjKzfjat4O1x3Kq4ASCYbzz3WD3fry3PVjb7N96cPz91uDqzxIzJE8O2L/xWXz/ZhYoKDkGE6/fifceJZoCvMpDNq8eX/ky3rkT/7SVXAEFvfq7P8SHiSXhUNZ0wXRsczkX6fjgm/4X1+LfN6G2vYODeOMWKpU4rdKdPO5uGlAfSqvkJZHoJUaHN5CMMufsic7nbFKk34ncGqGJKdHoed93CPYULhHorPVppKeWkRclQa4SnWRTydKA4xxxbVaYzIjJ5LRcdVFhdcFawKbyWoOjSRJPl9VIj4ykNmk5UkfNp3BleQ9bdgSVXMSsWca1sFBQOjFbhX1fLaISKqRqMCtMRVDtyWB1Mg3l2B5ZSPbqZRM7ZuFch9e0i6aSnVm8nILrvseWRMFz0CkhCRlcKhV/G1FmMg5YFUgU+o5tIXF+q1ldWUt5BHQ6yS7ogiZwZZMNO0Pcyqp9koLZ8nvwP5MQnWRZ6diM4IJI9cC34diiifipOHrTbxEKwQwWQhpEnynP8HUKiuWEqvsXUnaEYQ==) 嘗試從quasar的原始碼反向工程做出一樣的效果 第4課 ── 學習 Vue 的 v-model 觀念 [作業](https://play.vuejs.org/#eNrNVltv3EQU/iuDVdQN2mtuTc0m4iIh8YAEqtQXzIPXnt012B4zHm8SrRa1TSuVhrA8tAmKkKDqRakCSSsQDckGfgzr3eQpf4EzF3udTSraPvXB9pwz5z7nfOO29n4QFFsR1nStGlrUCdiC4TteQChDnyx/7AcRQ3VKPGRoxZJicHlDe9fw8ZKQs3HdjFyG2oaPkEVA2cc+C3XUTk108nzPNpmZm5ByCFHMIuonFEIOl7xquhHWkR+5rlBBqAOO4C0oD7MmsbllSS+azGqmFHcdMWynDI9EPtDcJWdwS9VSmiUQDHuBazIMFEJV22khyzXDcN7QasReNjTBhx2VRhKp7hEbuyJUEB3FbWiJxHtRAMni04I5Hy+K9QSaX0C5kR6aR+nWyIZr1rALanXHdbE94itaUKU3IkISMdfxszGmnEyU1RIUGFbVUqbsQIZs2eXLd2QreCZtOL6OyuLcA9O2Hb8hyY7hF/nBSMFFx2Zw+JVy+W0h2sROo8kEI2w1Bct2QnC0rKO6i5cEhy8KtkOxxRwCXiziRp4vtmqm9VWDQsvYBeASqiPaqOWm5vJo6hJ/JmQE0EEqYC2vZSaCT9BbhQI62l7tH/4zvLsV7/w4WP9ruHkzvrXSP/jz6Mnj4fdP4ueP4lvPT3qbV6GoVz76EH0K8UmvvBhNxoJQL5XCusVtfhkWCW2U+A6vI5iOD/aH26vJXHEZJM2f9L7r7z0e3N0ddP/o763GtzfiOz8frRxKzVZBnDMCRvzwl6Ot3+Kdzfha799r1+Puevz3BqyloDjSU2KDX2/2D9fiH9aGW89Oerfj7m7/4FF/b41nuNJFn0VmaFIUr94b3ts+vvFgsPXgqLt7vL8BAcVPnw2f3o/Xd47v7w4f7sc/bQ02rh/fuBOv/Q5mTnrfSp+yoRFoxr2uZCX9o5ioUFC9kgzvedATUALFSwBFZKKjK4xC/ygskZ509AEhLjZ9xU2cjfNHo8GhjC0H8FXmEscZuFIQJd/YczgAfm5oZ8bM0L54RSyyiM9MCJCOAElMZgqcdjLjowHUE+V2mrT85jPpplXujBR5mqDG8FLWWksBRDaNFEmEa9i8wLPOXTyT8cU8uoBbcCUUGcw2hq4dwxGKv45gJMcxTfZindBRegvttmrRTqdaEquXwpZiWkPVKiR0JABQDNJOCwsISLBnphxwuIBpN3zpbkzLrIUAHExqubguYEfoQAVJkKWo6ada0CWT5bIXIl52kwqBDNZU5qbyqHLpsngpuIHbWNygWcgDG8p6Co+TwHlppyOzep1YUYi+kUWFvpRcOCDHTrjStcgqsZ+JeW4mjyYrk/CameEhIxRapgszUS5eTlwV1YSrH4QX55sFYSkyC9A7O8sftU+ojUHdh3+MDKNQI4wRD+oAZYCjgejP01YNn6rzC0WNR5O0MIUCJLQsjIj4hS4Wm45qAVBiPKwa5XeQj8MwVymKesgCpJP2GiWYhhtoGpKYHitB5VSq5xg6L9t0+NN8U86ZjMddnD3q1MP/CZ5bn8rZG7XzH5rEyeY=) 同上 第5課 ── 學習 Vue 的 slots 觀念 [作業](https://play.vuejs.org/#eNqdVd1uG0UUfpWDEeJH3o0TCqkWUylBofiiroQbIaS9Ge+O7VHXM6uZsR0TWSoqkVADBFAFFarUIgpEKj8XVCjQwtNk3fQKHoEzM7trO2mo2ht7zpnv/M45325X1tLUHw5oJajUVSRZqs+FnPVTITVcGK8TzqmEjhR9CCv+UqExFmHljZDTLYuMaYcMEg3bIQeIBJpzyrUKYHvmZFI1lzHR5KWXHRBAUj2QHLYn6ApyRJ/qnoiNrZNHREe9UjLOB5rGpaIvBhxl49MojKf6UlkJCpr204RoihJAPWZDiBKi1JthpS3icVixerwpE5XoMaZxrgd4j0JE+IsaOozHMBYDCYoMaYzZRyylCjABlpgLUKzLgXHfBHbGZXgYeioROiCRZoKXzhHRHmiNmrcuNi81mpsbsNaCNTi/udG6VF/K7wpMq3G+CY1mqS+jLC1UaRRFObYJ/19go+OSJyPQPaagbWFVFGh+xkdANWW8C4pSDu2xsXimMt/faJ0oq3nxhOrfWzduPGWZRsTnxdMCDkWlx4k5vuLmrk9kl/EAanbqUhLHWJgTJyH3zVg44IjFGkdvuVZ7wUJ7lHV72irUsGdVMVMYaBxAV7LYarokRYSkfSuRBEfCiwTOKEdLpYnULk7IXXUuVFvImMoAOG6ONWyT6HLXvlSAE9Wjkhk7swCJQBz6jWg7GThwB/17in1AsQr/bBE7GkhlsKlgGF4eq9Z/rcClQjHzWgFONDaNDY1TzNDlFwSkg9bFbueFhBW7//PGpK1Egrtp1YwrijDX4lkt2Amb/qjHcqBIScQ0NtBBtSS8cJhfYaorChLGKTE1zLUu6IkhNm0+wZk7f8WBkQ3y569UK/MEZijvOc+DkB/d3c3u//nw7m7JVuYesp2rh/d//+fBJ4cHP0yv/zrdu3d4sJt9/HV27dbR1b9C/uj250f7Pz/85iMwIw+oy+7cnl7/O9v5Ptv5KfviWrbzY/bLHyF3yzCPym7uo6/DgyvTz76c3ryS7f2WfXjPmT769tPszleFab6rMN3/LnuwB55nxrukt8fRbypFapk3Nw1gXYiEEm759Wn40Tw2wbbLGUma66C4nwuRH6o5XwT4jtjACRrWTdXnMKT7cwta+ipcuQ4VcOCkTxe0x82ftOl+mXvelFNG3M/5LeeFLW+28mo4esxurZZbY/WjnBHO1Nz4min1SprwV0p0QjXOqKfMeLr1qy2vnn193leH9FmCk/uuaAstquCRNE2op8YKa6zC2pByhqy8jjEuXyBRy+rfRssqtGhXUNhs2C8iwDs0GVLNIoJWkpGkitzOlaeQRDqnLOTzq+3lDjErcwrFlMRhqC1nD3jVlWcamc/4sW4vcIIWyIy5CX77XZNKuWTSTkK3XFfw4I2k4VPze4JdLRP4xYbM0agnScwGuARnUuNpkQQm/wFjNTqv) 嘗試模仿quasar拼裝不同呃component 第6課 ── 學習用外部狀態管理 vue 元件 [作業](https://play.vuejs.org/#eNrtVktvFEcQ/ivFhshrsi+bWEo2hgBOohwgQiBx2gO9M727HWamx909axtrTwQFsBUOIRA45KEQHkJAFEUBYkj+jGdtn/gLqX7M7KyxwcohyiF7mO2u/rq6q+qrql4uHY3jWj+hpWZpVnqCxepwK2JhzIWCE0vHEqV4BB3BQ2iVavVMone0Sh8UkB8xEvBuEWklObIV0UWD9WmHJIGC5VYE4HFUENFIySYsw/wxFTXzYyswb3VokdM/qOhdPlGkPGk1AAiqEhHhdhJQoZrQIYGkFVQddZgI3RwGeAdw+0OqetzXR1oNZuPU9MGRTicro3DSbMy22u8CUV4Pt9uZNiJR1M8FIU8inGt1WqCPnq3n3sWJomEcEEVxBjA7X20rlOpDAtKmwaFW6ag+vVWyQo8HXKCwHRDvXCZUdFFVs5WFHlPoZrvSlOw8ReFUJhB4Hd8Oj8REoLertI9fxBgr4RDsMwO74fBs3dwou5xvXd+vhtw3l3NYs44In/XdEOA4FzQEFsskBF9fDiRTQNDhOh6SekoHC4jPYiaZx6Iu0ICpGpyiArcIGtMgoJGfyEyj3t/nQRIr9Fc2kqANYKgVKSV4th0dFPlMMSYhpqJD0VQfx4orEprA6B8lQBTwMMKVPg0gSsL5hIRAF6nwGJ7CkJAhkERVICIqkRAy5Dmp2LN0iNDImjO+PrK+GMdRJOeOc5mHZpdYvi6aO8RzLKJ7i6n+dQJO9Lpg3V4uHg82jm20dyXmnM2qf4GaLn+1IW64R3rm6P8J+t8k6G6R/Qckna0XSilOpVoK9PCALeQhEV2GLaVhanhMfB8DaqeDVtTm/pLFLTBfYT2fajTeNsge1ccbgez3jKiN7ugas6wbmvDWND3oHaRWF9Z3d3SpUio2v7HGulMLjAWPTfcz/D1DgoQ24RjnASWRaTdvah8YYPACIqV1rSIsoqJVwoxgHRSN1I5lRL5F9ojPF3BtjCpFxAKLECE1RAZcIdD9ZfhstFs0avm1nMkckwZZ3ATSlpgwSjsRgGH+odNtsDAvUNNSE7qC+TZ8yEiKzsfWGiHMwy8V1vujA5pt2kH2Z68Lh0Ui6TfI3k5+NdKi2y5PvT9dgemp9/Az494EPCaYj3jFRm3GCDoswCs1oW3YG1Epy7hkweer6EW6mJOv5rzqPJJRcwrL025863Q6Zikki1XH2JlGI160eC58KqoCK1eCdHrXifNjp7Ydexi250htxp79KptHjz7N5n3VKmw+WFl/8dfGtXvpo2+H159t3PoivXhhfe33zft3Nr66nz75Ob345OXzW2cSCqc/mYOTGElrjOZFTylkfL0uO57W+bmscdGt6xVNPVSdrv2x8WAlfwhqEFj9L5+vrj+9M7z2eHj1t/WnK+mlG+mV7zcvvCh0I8BpevuHzXsP00e3Ni+sDm8+3vrx6ublX7c3pzHg8PqX6cMbRaCpjztg0ot300fPLEYXvnHI6uWtS9+kt++mv1wtdDgY3vspfe4kEqs5MrQoOuIFzDs3pmlr7bvh11fSP1fRt+tra+nKTahWdY7tqZgU/NGE00ogt1x/0fbP7SA35m6TafOa8FkStqlwIlOft8GMiXnNyvYaK7dL+3MBdpuTMY+TeHxtL5WubejgbHPFKXQkyXqFdSUu7KchU+UJ23s+1q1nomKtnBw9RzTLEZu/+kdZhwVGeynvys6XufvyBZt4p1zenSCqV8PaUi7bwH+IKQqYXJNQhbKLPMqMaBLegYl4cSJXFWAF+9S1nrMeCbzy/mUdgwHmqk3PybM5uIPF7bQJ0Bj0gCkhBVxeWt6o0VqyE7BhkIAVk/n6EeOdK9zDMsL8OeHAvdTsbHnZ5dIAK4tuFjaMr+sXWVAtkYtBifDtU6h3BYGXCKkjFHPmGgOSXZAoK/gSraIw3WiE+Dgj0vXt/Khmj/ez/mSgWDJrrmgWyuHgb/u4VhA=) 稍微翻了quasar的原始碼,還是搞不懂為何上一個v-close-popup的attribute就可以讓按鈕有關掉modal的功能 很神奇 第7課 ── 學習開發狀態複雜的 vue 元件 [作業](https://play.vuejs.org/#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) 研究了前輩的作業才發向若要讓input的值可以被檢查就不能限定number,要不然輸入非number會直接show出來,卡這個很久... 因為想學quasar的樣式(range條的顏色變化等)做了些研究,後來嘗試把所有想法塞進去,結果做出來是蠻炫的但不是很好看... 心得:覺得老師的出題方向就是幫助學生從業界的需求去學習,然後一點一點從小地方開始做,並且能夠自行研究,而且不強調怎麼寫,而是確實做出來,很務實的取向,覺得獲益良多,上完9堂課默默繳了不貴的學費,有新的課堂會再回來做。 目前正嘗試自行開發一個網頁應用,寫cdoe真的要很有耐心,其實想想現在有很多輔助/查詢工具真的很方便,越寫越佩服那些做框架的人...

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

## 介紹 程式碼重構,在不改變外部功能的情況下改進現有程式碼。它是寫程式的核心部分之一,不容忽視,否則您將無法獲得更好的程式碼。程式碼重構可以增強程式碼的可讀性、可維護性和可擴展性。它還能提高性能並提高開發人員的工作效率。 今天,我們將研究一些可以幫助您重構程式碼的技術。 原文出處: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。 ## 結論 重構是任何想要提高程式碼質量、性能和可維護性的開發人員的基本實踐。通過花時間分析和優化您的程式碼,您可以消除冗餘、降低複雜性並建立更高效和可擴展的應用程式。 通過不斷審查和改進您的程式碼,您可以建立更健壯和更有彈性的應用程式。

發文點子

分類: 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)

發問-教學經驗的累積?或是說教學風格的培養?

## 前情提要 自學程式對某部分人來說,是一個不太難的事情, 學習能力好,悟性高、執行力強就有辦法可以做到,這屬於自學型人才。 像我自己就有能力可以自學到一定的程度。 但當這樣子的人要轉變成教學模式,當一個家教或老師,似乎是另一回事, 並非技術研究的越深,越會教,而是要針對教學下功夫....(? ## 舉例說明 像是我有觀察教學前端的課程設計,有的是從CSS開始, 一堂教reset跟html,一堂教margin,做出各種練習。 再來可能是padding,以此類推,這樣。 通常都是這種零件式的學習,分散大架構,東西拆開來解說。 這樣子可能可以教一個禮拜之類的, 但其實對熟練的人來說用個簡單的模板網頁,十分鐘內一定能做完。 這之間有點矛盾或說,有差別。 ## 疑惑內容 想請教前輩或是站長在這方面有沒有心得, 教學上追求循序漸進似乎是必要的,講白一點就是進度比較慢啦! 不知道這種狀況前輩們是否有遇過? 目前有在規劃假設要教人的話,是否就是慢慢來,給人家操作看看練習, 但感覺又很像在拖時間XD (因為我自己跟人家線上試上過也會覺得,有點慢,資訊量很難跟自學比) 雖然我個人不傾向於這種學習模式, 但我知道要把十分鐘弄完的東西,轉化成:解說成那麼多堂課,是另一個領域的一種功力.... 我想這應該是有些人走過的路,心態上有點不確定,因此想請益一下這塊的經驗跟心得~ 任何關於家教的想法,歡迎站長或是前輩們稍微分享看看 教育這條準備的道路心得~~

我推薦 Svelte 給所有工程師的 10 個理由

原文出處:https://dev.to/mhatvan/10-reasons-why-i-recommend-svelte-to-every-new-web-developer-nh3 儘管 [Svelte](https://svelte.dev/) 的初始版本早在 2016 年 11 月就發布了,但它在 JavaScript 前端框架中仍然處於劣勢,並且最近才開始受到社區應有的關注。 在使用了多年的各種 JavaScript 框架(包括 Angular、React 和 Vue.js)之後,我認為我對編寫程式碼如何愉快以及如何令人沮喪有了良好的總體印象。 幾年前,使用 [jQuery](https://jquery.com/) 編寫程式碼感覺就像來自純 JavaScript 的啟示。然後在我的第一份工作中,我開始使用 Angular 2,突然間 jQuery 感覺像是一個拖累。現在,React 是最酷的孩子,相比之下,Angular 感覺太複雜了。您可能會看到這是怎麼回事! 對我來說,Svelte 是快速變化的 JavaScript 框架生態系統中的下一個進化步驟。用 Svelte 的方式編寫感覺很容易,你可以看出它的建立者 [Rich Harris](https://twitter.com/Rich_Harris)厭倦了現有框架要求您學習的所有煩人的抽象和必要的樣板程式碼。 現在你可能會問自己這個問題: ## 是什麼讓 Svelte 與眾不同? 您可能聽說過 Svelte 出現在諸如 [前端框架的真實世界比較](https://medium.com/dailyjs/a-realworld-comparison-of-front-end-frameworks-2020-4e50655fe4c1) 和 [State of JS Survey](https://2019.stateofjs.com/front-end-frameworks/) 等開發人員調查將其列為在捆綁包大小、性能、程式碼行數方面排名最好的框架之一以及最重要的開發者滿意度。 與流行的 [React](https://reactjs.org/) 和 [Vue.js](https://vuejs.org/) 庫相比,它們在執行時執行大量工作並使用一種稱為“虛擬”的技術DOM diffing”用於檢測變化,Svelte 作為建置步驟被編譯成無框架的 vanilla JavaScript,因此可以從大量程式碼優化中受益。 出於本能的猶豫,我起初將 Svelte 視為“只是另一個 JavaScript 框架”而不予考慮,也沒有費心去研究它。第二次聽說後,我想知道:Svelte 是炒作還是真的那麼好?我決定對它進行實戰測試並將其用於我的個人專案。 現在幾個月後,我可以給你一個明確的答案: ## Svelte 簡單、強大且優雅,您會愛上它! 事不宜遲,以下是我向每位開始學習編程的新 Web 開發人員推薦 Svelte 的十大理由: ## 1. Svelte 元件易於理解 如果您以前從未見過 Svelte 語法,這就是一個簡單示例的樣子: https://gist.github.com/mhatvan/3630989d364e4020f26ebb96d2d7c332 與其他引入大量抽象概念、需要花時間學習和理解的前端框架相比,看到 Svelte 只是並排使用普通的舊 HTML、CSS 和 JavaScript,真是令人耳目一新。您可以通過其對初學者友好的語法查看並輕鬆辨識此處發生的情況。 ## 2.簡單寫簡潔的程式碼 正如您在上面的程式碼示例中看到的,您編寫的業務邏輯既簡單又易於閱讀。畢竟,您編寫的程式碼越少,錯誤就越少,對吧? Svelte 的天才創造者 Rich Harris 在他的文章 [少寫程式碼](https://svelte.dev/blog/write-less-code) 中對 React 和 Vue.js 進行了一些很好的比較。根據他對編寫簡單的兩個數字相加邏輯所需的字符的檢查,React 元件通常比其 Svelte 元件大 40% 左右! ## 3. 與標記語句的反應性 每當您希望根據其他變數更新和重新計算變數值時,您可以使用反應式聲明。只需在您想要響應的變數前面放一個美元符號,您就可以開始了! https://gist.github.com/mhatvan/7e2f0fea362c79d64a34cb7e0c088453 每次單擊按鈕時,`count` 將增加 1,而 `doubled` 將知道 `count` 的值發生變化並相應地更新。從反應性的角度思考真的很有趣,而且寫起來感覺很好。 ## 4.開箱即用的簡單全局狀態管理 無需任何復雜的第三方狀態管理工具,如 [Redux](https://redux.js.org/) 或 [Vuex](https://vuex.vuejs.org/)。 您只需將一個變數定義為可寫/可讀存儲,並在任何以 `$` 符號為前綴的 `.svelte` 文件中使用它。 https://gist.github.com/mhatvan/710b6bb6df4ece7e9a5f53886eb2dd0d 在此示例中,我們檢查當前環境,它作為值存在於我們的商店中,並使用它來決定是否應顯示 cookie 通知。很簡單,不是嗎? 使用 Svelte 存儲,您也永遠不必擔心內存洩漏,因為以 `$` 符號為前綴的存儲變數充當自動訂閱和自動取消訂閱。 ## 5. 內置可存取性和未使用的 CSS 檢查 Svelte 希望讓網路變得更美好,並通過程式碼中的有用提示幫助您。 每當您忘記將 alt 屬性放在 `<img>` 標籤上時,Svelte 都會為您顯示 `A11y: <img> 元素應該有一個 alt 屬性` 提醒。在 Svelte 中實現了一長串可存取性檢查,它們會提示您而不會成為麻煩。 為了使程式碼盡可能簡潔並避免遺留程式碼片段,只要在元件中找不到相應的標記,Svelte 還會為您標記未使用的 CSS 選擇器。 ## 6.元件自動導出 每當你想在元件 B 中使用元件 A 時,你通常需要先編寫程式碼導出元件 A,這樣它才能被元件 B 導入。使用 Svelte,你永遠不必擔心忘記導出, `.svelte` 元件始終默認自動為您導出,並準備好由任何其他元件導入。 ## 7. 默認情況下樣式是有範圍的 類似於 [CSS-in-JS](https://webdesign.tutsplus.com/articles/an-introduction-to-css-in-js-examples-pros-and-cons--cms-33574) 庫,Svelte默認情況下,樣式是有範圍的,這意味著 `svelte-<unique-hash>` 類名將附加到您的樣式,因此它們不會洩漏和影響任何其他元件樣式。當然,您可以選擇全局應用樣式,只需在它們前面加上 `:global()` 修飾符,或者如果您願意,也可以只使用 `.css` 文件。 ## 8. #await 塊 對於大多數 Web 應用程式,您將需要處理異步資料以向用戶顯示有用的統計訊息。 https://gist.github.com/mhatvan/2e44dc1ec402f477830f90bd77614f34 `{#await}` 塊的優點是您不必為已解決/拒絕的承諾定義額外的狀態,您只需在模板中定義內聯變數即可。 ## 9.傳遞道具的速記屬性 如果存在與變數名稱相同的 prop 名稱,我們可以將其作為簡寫屬性傳遞給元件,如下面的“{message}”。與使用 `message="{message}"` 相比沒有任何優勢,但更簡潔。 https://gist.github.com/mhatvan/9085f5330eeccdc2238e4f4e609b4f88 在上方,您可以看到根據 round 是真還是假將 class:round 屬性應用於按鈕。這很容易成為一個可重用的元件,您可以從外部傳遞 `round` 的值來有條件地決定元件的樣式。 ## 10.內置效果和動畫 Svelte 預裝了強大的效果模塊: - `svelte/motion` 效果,如補間和彈簧 - `svelte/transition` 效果,如淡入淡出、模糊、飛行、滑動、縮放、繪製 - `svelte/animate` 效果如翻轉 - `svelte/easing` 效果,如彈跳、立方體、彈性等等 Svelte 官方教程中有幾個示例,但我最喜歡[這個進度條示例](https://svelte.dev/tutorial/tweened),因為它很簡單。 動畫是 web 開發的一個領域,您通常會在其中尋找外部依賴項來為您處理它,因此您可以開箱即用地使用它們真是太好了。 ## 不採用 Svelte 的合理理由 為了避免讓這篇文章聽起來像一篇冗長的狂熱帖子,以下是我迄今為止使用 Svelte 時遇到的缺點: ### `.svelte` 文件不能導出多個元件 一方面,我們受益於默認自動導出的 .svelte 文件,但這也意味著我們無法從單個文件導出多個元件。我不認為這有什麼大不了的,因為它會迫使您遵循最佳實踐來使用許多小的獨立元件編寫您的應用程式,這使它們易於理解和單元測試。 ### 一般模板語法 為了顯示條件邏輯,Svelte 使用類似於眾所周知的 [Handlebars](https://handlebarsjs.com/guide/builtin-helpers.html#if) 模板語法的語法。 https://gist.github.com/mhatvan/95cc1837441a272cb8422fcae24d91e0 這種編寫邏輯的方式我沒有遇到任何問題,但我更喜歡更簡潔的語法。 ### 使用 export let 在子元件中接收 props 當您想要將值從父元件傳遞到子元件時,您需要將一個值作為屬性傳遞,並使用帶有匹配變數名稱的 export let 來接收它。 https://gist.github.com/mhatvan/b67ceafb05d21c15b5782c068690d632 在現代 JavaScript 中,`export` 通常用作導出模塊的關鍵字和 `let` 聲明塊範圍變數,所以我覺得語法濫用現有關鍵字,但我習慣了它並且效果很好. ###開發速度 這與 Svelte 的開發體驗沒有直接關係,但您絕對應該知道,在財務支持方面,Svelte 無法(目前)與更大的和讚助的開源專案競爭,如 React、Angular、Vue.js 和其他專案,截至目前的貢獻者數量和受歡迎程度。 儘管如此,社區正在迅速發展,社區為 Svelte 建置的第三方專案列表也在不斷增加,這些專案可在 [Made with Svelte](https://madewithsvelte.com/) 上找到。開發 Svelte 相關工具的開發人員都是天才,您可以隨時在 [Discord](https://discord.com/invite/qa4pnmw) 頻道、[Twitter](https://twitter.com/sveltejs) 上尋求幫助) 或 [Reddit](https://reddit.com/r/sveltejs)。 Svelte 最近還加入了 TypeScript 支持,而且效果很好! 我喜歡 Svelte 的易用性、較小的包大小和開發人員體驗等因素,因此我可以接受較慢的開發速度作為權衡。如果您總是需要盡可能快地合併最新功能,那麼您可能需要查看其他可用的 JavaScript 框架。 ### 缺少可用的工作 大多數公司仍在尋找對三大前端框架有經驗的開發人員,但也有各種知名的 Svelte 早期採用者,如 IBM、Apple、Philips、GoDaddy、1Password 或紐約時報,僅舉幾例.您可以在 [Svelte 網站](https://svelte.dev/) 底部找到大量使用 Svelte 的公司。通常,採用新框架需要一段時間才能出現在公司的工作機會中。儘管如此,Svelte 學習起來很有趣,許多開發人員喜歡使用 Svelte,尤其是在他們自己的個人專案或小規模應用程式中。 ## 結論 如果對初學者友好的語法、較小的包大小輸出和 Svelte 的瘋狂性能對您來說是一個不錯的選擇,我建議您開始使用 [Svelte 教程](https://svelte.dev/tutorial/basics)。該教程非常詳細,您可以快速了解該框架的強大功能。 在 JavaScript 框架的世界裡,事情肯定會快速變化,我希望你和我一樣相信 Svelte 擁有所有的優勢和潛力,可以讓它成為新的 #1 JavaScript 前端框架! 您之前使用過 Svelte 嗎?你的經驗是什麼? 在評論中告訴我,我很想知道。 感謝閱讀,希望您喜歡! ## 有用的資源 - [Svelte 教程](https://svelte.dev/tutorial/basics) - [Svelte REPL](https://svelte.dev/repl) - [Rich Harris - 重新思考反應性](https://www.youtube.com/watch?v=AdNJ3fydeao) - [為什麼要苗條](https://github.com/feltcoop/why-svelte) - [為什麼 SvelteJS 可能是新 Web 開發人員的最佳框架](https://dev.to/bholmesdev/why-sveltejs-may-be-the-best-framework-for-new-web-devs-205i) - [為什麼我們從 React 轉向 Svelte](https://medium.com/better-programming/why-we-moved-from-react-to-svelte-f20afb1dc5d5) - [我喜歡 Svelte 的寫作風格](https://css-tricks.com/what-i-like-about-writing-styles-with-svelte/) - [我在 React 和 Svelte 中建立了完全相同的應用程式。這是差異。](https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-svelte-here-are-the-differences-c0bd2cc9b3f8) ## 正在尋找 Svelte 支持的伺服器端渲染解決方案? 在使用 [Sapper](https://sapper.svelte.dev/) 接觸框架後,我是一個忠實的粉絲,一有機會就嘗試推廣 Svelte 之道。 如果您要建立一個網站並正在尋找合適的工具,我發表了一篇關於我迄今為止使用 Sapper 的經驗的文章,供您在此處閱讀:[“為什麼我為我的網站選擇 SapperJS,以及我做了什麼”到目前為止,我已經了解了該框架”](https://markushatvan.com/blog/why-i-chose-sapperjs-for-my-website-and-what-ive-learned-about-the-framework-so-遠的)。

JavaScript 系列九:結語

恭喜你完成了一系列酷炫的元件 Quasar 是業界最頂尖、好用的 UI 元件包之一 你在這系列作業中,也順便學習了此元件包的用法,這在實務上非常有幫助 你甚至親手製作了其中一些基本的元件,讓你大致了解元件包背後的製作原理 像這些最基礎的 UI 元件,因為通用性很高、很常被重複用到、在多個地方到處使用,所以很適合製作成元件 --- 但是,在實務上,通常開發一個頁面,就製作一個 vue 檔案即可。除了基礎 UI 元件之外,並不會額外製作多少元件 因為頁面上很多看起來像元件的東西,其實就算拆出來,別的頁面也用不到、或根本無法使用 這種情況,其實也不用刻意要拆成元件,因為意義不大,說不定還會變更亂。切記:不需要為了元件化而元件化 當你發現頁面真的有點太複雜、你明顯感受到拆成多個元件會比較好維護的時候,再拆成元件就可以了 --- 翻閱 Vue 官方文件,你會發現 `Components In-Depth` 這個段落,你幾乎通通讀完了 有些我認為非必要、沒那麼常用的段落,就沒有指定讓你閱讀。你如果好奇的話,就自行把官網剩下的頁面翻一翻吧 必要的元件觀念,你都已經知道了,這些已足夠讓你參與團隊合作、與團隊一起開發應用程式了 但是在真正大型的專案,還需要引入一些進階觀念、生態系工具 這些會在後續的課程提到! --- 消化、研究完本課程之後,我認為你已經具備入行前端工程師的基礎能力了! 急著上班、找工作的同學,請參考我寫的文章: **給寫完 JavaScript 系列九的同學們:求職前的準備&簡易指南** https://codelove.tw/@howtomakeaturn/post/k31dYx 再次恭喜你順利完成本系列轉職前端課程,祝你求職順利! 有問題可以多多上來發問!

15 個 JavaScript 日常操作的實用、簡潔寫法

這裡有多種簡短而強大的 JavaScript 技巧,可以最大限度地提高生產力 ⚡️ 並最大限度地減少痛苦 🩸。 讓我們深入研究看看🤘 原文出處:https://dev.to/ironcladdev/15-killer-js-techniques-youve-probably-never-heard-of-1lgp ### 唯一陣列 過濾掉陣列中的重複值。 ``` const arr = ["a", "b", "c", "d", "d", "c", "e"] const uniqueArray = Array.from(new Set(arr)); console.log(uniqueArray); // ['a', 'b', 'c', 'd', 'e'] ``` ### 唯一的物件陣列 `Set` 物件不允許您過濾掉重複的物件,因為每個物件都是不同的。 `JSON.stringify` 在這裡幫我們解決了這個問題。 ``` const arr = [{ key: 'value' }, { key2: 'value2' }, { key: 'value' }, { key3: 'value3' }]; const uniqueObjects = Array.from( new Set( arr.map(JSON.stringify) ) ).map(JSON.parse) console.log(uniqueObjects); ``` 在 [此評論](https://dev.to/jonrandy/comment/24ojn) 中查看更有效但稍長的方法。 ### 陣列迭代器索引 通過 `.map` 和 `.forEach` javascript 迭代函數,您可以獲得每個項目的索引。 ``` const arr = ['a', 'b', 'c']; const letterPositions = arr.map( (char, index) => `${char} is at index ${index}` ) ``` ### 按字元數拆分字串 我們可以使用 `.match` 正則表達式函數將字串拆分為 `n` 個字符。 ``` const str = "asdfghjklmnopq"; const splitPairs = str.match(/.{1,2}/g); console.log(splitPairs); // ['as', 'df', 'gh', 'jk', 'lm', 'no', 'pq'] ``` ### 用不同的字元拆分字串 另一個使用 .match 的正則表達式 hack 允許您將像“aabbc”這樣的字串拆分為陣列“[”aa”,“bb”,“c”]`。 ``` const str = "abbcccdeefghhiijklll"; const splitChars = str.match(/(.)\1*/g); console.log(splitChars); // ['a', 'bb', 'ccc', 'd', 'ee', 'f', 'g', 'hh', 'ii', 'j', 'k', 'lll'] ``` ### 遍歷物件 `Object.entries` 允許我們將 JSON 物件轉換為鍵值對陣列,從而使我們能夠使用循環或陣列迭代器對其進行迭代。 ``` const obj = { "key1": "value1", "key2": "value2", "key3": "value3" }; const iteratedObject = Object.entries(obj) .map(([key, value]) => `${key} = ${value}`); console.log(iteratedObject); // ['key1 = value1', 'key2 = value2', 'key3 = value3'] ``` ### 鍵值陣列到物件 您可以使用“Object.fromEntries”將“Object.entryified”鍵值對陣列轉換回物件 ``` const entryified = [ ["key1", "value1"], ["key2", "value2"], ["key3", "value3"] ]; const originalObject = Object.fromEntries(entryified); console.log(originalObject); // { key1: 'value1', ... } ``` ### 發生次數計數 您可能想計算一個專案在陣列中出現的次數。我們可以使用帶有迭代器的 .filter 函數來完成此操作。 ``` const occurrences = ["a", "b", "c", "c", "d", "a", "a", "e", "f", "e", "f", "g", "f", "f", "f"]; // creating a unique array to avoid counting the same char more than once const unique = Array.from(new Set(occurrences)); const occurrenceCount = Object.fromEntries( unique.map(char => { const occurrenceCount = occurrences.filter(c => c === char).length; return [char, occurrenceCount] }) ) console.log(occurrenceCount); // { a: 3, b: 1, c: 2, ... } ``` 在 [此評論](https://dev.to/jonrandy/comment/24ojn) 中查看可靠的單行程式碼以執行此操作! ### 替換回調 `.replace` 函數並不限制您只能用固定字串替換。您可以將回調傳遞給它並使用匹配的子字串。 ``` const string = "a dog went to dig and dug a doggone large hole"; const replacedString = string.replace(/d.g/g, str => str + "gy") console.log(replacedString); // a doggy went to diggy and duggy a doggygone large hole ``` ### 條件串接 你們中的許多人都熟悉在 JS 中遇到未定義的錯誤,條件連結可以防止很多這種情況的發生。 > **可選連結** (`?.`) 運算符存取物件的屬性或呼叫函數。如果使用此運算符存取的對像或呼叫的函數未定義或為空,則表達式短路併計算為未定義,而不是拋出錯誤。 ``` const obj = { "a": "aaaaaaa", "b": null }; console.log(obj.b.d); // throws an error console.log(obj.b?.d); // returns undefined ``` ### 限定一個數字 通常,您可能需要將數字限制在特定範圍內。每次需要時都用三元運算符來做是一件很痛苦的事情。函數要乾淨得多。 ``` const constrain = (num, min, max) => { if(num < min) return min; else if(num > max) return max; else return num; } constrain(5, 1, 3) // 3 constrain(2, 1, 5) // 2 constrain(0, -100, 100) // 0 ``` 一個更好的方法是像這樣使用 `Math.min` 和 `Math.max`: ``` const constrain = (num, min, max) => Math.min(Math.max(num, min), max) ``` ### 索引陣列的前後 `.at` 函數允許您使用正數和負數從頭到尾對陣列進行索引。 ``` const arr = [1, 2, 3, 4, 5]; arr.at(0) // 1 arr.at(1) // 2 arr.at(-1) // 5 arr.at(-2) // 4 ``` ### 按字母順序排序 按字母順序對字串陣列進行排序 ``` const words = ["javascript", "typescript", "python", "ruby", "swift", "go", "clojure"]; const sorted = words.sort((a, b) => a.localeCompare(b)); console.log(sorted); // ['clojure', 'go', 'javascript', 'python', 'ruby', 'swift', 'typescript'] ``` 💡 **提示**:您可以通過將 `a.localeCompare(b)` 切換為 `b.localeCompare(a)` 來切換升序和降序 ### 按 Truthy/Falsy 值排序 您可以按真值/假值對陣列進行排序,將具有真值的值放在最前面,然後是假值。 ``` const users = [ { "name": "john", "subscribed": false }, { "name": "jane", "subscribed": true }, { "name": "jean", "subscribed": false }, { "name": "george", "subscribed": true }, { "name": "jelly", "subscribed": true }, { "name": "john", "subscribed": false } ]; const subscribedUsersFirst = users.sort((a, b) => Number(b.subscribed) - Number(a.subscribed)) ``` `Number(false)` 等於 0,`Number(true)` 等於 1。這就是我們如何通過排序函數傳遞它。 ### 四捨五入到 `n` 位 您可以使用 .toFixed 將小數四捨五入為 n 位。請注意,`.toFixed` 將數字轉換為字串,因此我們必須將其重新解析為數字。 ``` console.log(Math.PI); // 3.141592653589793 console.log(Number(Math.PI.toFixed(2))) ``` --- 感謝閱讀✨!

22 個很好用的 CSS 小訣竅&特殊小技巧

**🚨🚨注:**本文分享的所有tips、tricks都是GitHub repository[【css tips tricks】](https://github.com/devsyedmohsin/css-tips-tricks)的一部分。覺得有用的話請查看資源庫並給它一個star🌟 原文出處:https://dev.to/devsyedmohsin/22-useful-css-tips-and-tricks-every-developer-should-know-13c6 ## 1. Docs Layout 僅用兩行 CSS 建立響應式文件樣式的佈局。 ``` .parent{ display: grid; grid-template-columns: minmax(150px, 25%) 1fr; } ``` ![佈局](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojs8nvly2ugashxwqif8.png) ## 2.自定義游標 查看 github 存儲庫 [css 提示技巧](https://github.com/devsyedmohsin/css-tips-tricks) 以了解更多訊息。 ``` html{ cursor:url('no.png'), auto; } ``` ![帶有自定義光標的圖像](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ba8kist57vp6l9spw8w2.gif) ## 3. 用圖片填充文本 ``` h1{ background-image: url('images/flower.jpg'); background-clip: text; color: transparent; background-color: white; } ``` ![Air Max](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0a7my28raxr80upv77k1.png) **注意:** 在使用此技術時始終指定 `background-color`,因為這將用作後備值,以防圖像因某種原因無法加載。 ## 4. 給文本加入描邊 使用 text-stroke 屬性使文本更易讀和可見,它會向文本加入筆劃或輪廓。 ``` /* 🎨 Apply a 5px wide crimson text stroke to h1 elements */ h1 { -webkit-text-stroke: 5px crimson; text-stroke: 5px crimson; } ``` ![NETLIFY](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h9xcwsh18vxqw1uaj5h3.png) ## 5.暫停 Pseudo Class 使用 `:paused` 選擇器在暫停狀態下設置媒體元素的樣式 同樣 `:paused` 我們也有 `:playing`。 ``` /* 📢 currently, only supported in Safari */ video:paused { opacity: 0.6; } ``` ![河上的棕櫚樹](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dq1za9uri1a37kqyh1y1.gif) ## 6.強調文字 使用 text-emphasis 屬性將強調標記應用於文本元素。您可以指定任何字串,包括表情符號作為其值。 ``` h1 { text-emphasis: "⏰"; } ``` ![時間是良藥](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6l1oifo8erkkblsk7ilt.png) ## 7.樣式首字下沉 避免不必要的 `<span>`,而是使用偽元素來為您的內容設置樣式,就像 `first-letter` 偽元素一樣,我們也有 `first-line` 偽元素。 ``` h1::first-letter{ font-size: 2rem; color:#ff8A00; } ``` ![Gitpod.io](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1jtvgnx1y1xqf0sd9b7.png) ## 8.變數的回退值 ``` /* 🎨 crimson color will be applied as var(--black) is not defined */ :root { --orange: orange; --coral: coral; } h1 { color: var(--black, crimson); } ``` ![深紅色文字“說話,你很重要”](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2477mnixnrwtwn5mqun.png) ## 9. 改變書寫模式 您可以使用書寫模式屬性來指定文本在您的網站上的佈局方式,即垂直或水平。 ``` <h1>Cakes & Bakes</h1> ``` ``` /* 💡 specifies the text layout direction to sideways-lr */ h1 { writing-mode: sideways-lr; } ``` ![文本開始於](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ozqs02sh7edl70cd609a.png) ## 10.彩虹動畫 為元素建立連續循環的彩色動畫以吸引用戶注意力。閱讀 [css 提示技巧](https://github.com/devsyedmohsin/css-tips-tricks#rainbow-animation) 存儲庫以了解何時使用“prefer-reduced-motion”媒體功能 ``` button{ animation: rainbow-animation 200ms linear infinite; } @keyframes rainbow-animation { to{ filter: hue-rotate(0deg); } from{ filter: hue-rotate(360deg); } } ``` ![立即購買按鈕不斷改變顏色](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60jgrr09vgsckx9h2irl.gif) ## 11.掌握Web開發 訂閱我們的 [YouTube 頻道](https://www.youtube.com/@nisarhassan12),讓您的網絡開發技能更上一層樓。 [最近的視頻系列](https://www.youtube.com/watch?v=1nchVfpMGSg&list=PLwJBGAxcH7GzdavgKlCACbESzr-40lw3L) 之一介紹了建立以下開源[投資組合模板](https://github.com/nisarhassan12 /投資組合模板)。 ![伊蒙](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxid827qfq1ybx2tl3q7.gif) ## 12. 懸停時縮放 ``` /* 📷 Define the height and width of the image container & hide overflow */ .img-container { height: 250px; width: 250px; overflow: hidden; } /* 🖼️ Make the image inside the container fill the container */ .img-container img { height: 100%; width: 100%; object-fit: cover; transition: transform 200m ease-in; } img:hover{ transform: scale(1.2); } ``` ![躺在灰色瓷磚上的深紅色購物袋](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cxy8ymu937e0kf14wwbc.gif) ## 13.屬性選擇器 使用屬性選擇器根據屬性選擇 HTML 元素。 ``` <a href="">HTML</a> <a>CSS</a> <a href="">JavaScript</a> ``` ``` /* 🔗 targets all a elements that have a href attribute */ a[href] { color: crimson; } ``` ![HTML CSS JavaScript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1sq2rhs58a01ayfqzexk.png) ## 14. 裁剪元素 使用 `clip-path` 屬性建立有趣的視覺效果,例如將元素剪裁成三角形或六邊形等自定義形狀。 ``` div { height: 150px; width: 150px; background-color: crimson; clip-path: polygon(50% 0%, 0% 100%, 100% 100%); } ``` ![三角形](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9eqxif34ndhq33xvlpb.png) ## 15.檢測屬性支持 使用 CSS `@support 規則` 直接在您的 CSS 中檢測對 CSS 特性的支持。查看 [css 提示技巧](https://github.com/devsyedmohsin/css-tips-tricks#check-if-property-is-supported) 存儲庫以了解有關功能查詢的更多訊息。 ``` @supports (accent-color: #74992e) { /* code that will run if the property is supported */ blockquote { color: crimson; } } ``` ![永遠不要食言。(Hazrat Ali A.S)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ekr2fmhl4ori47xqgyf.png) ## 16. CSS 嵌套 CSS 工作組一直在研究如何向 CSS 加入嵌套。通過嵌套,您將能夠編寫更直觀、更有條理和更高效的 CSS。 ``` <header class="header"> <p class="text">Lorem ipsum, dolor</p> </header> ``` ``` /* 🎉 You can try CSS nesting now in Safari Technology Preview*/ .header{ background-color: salmon; .text{ font-size: 18px; } } ``` ## 17.箝制函數 使用 `clamp()` 函數實現響應式和流暢的排版。 ``` /* Syntax: clamp(minimum, preferred, maximum) */ h1{ font-size: clamp(2.25rem,6vw,4rem); } ``` ![gif 字體大小根據屏幕大小改變](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/upaf9jdlfapezzmufyaa.gif) ## 18. 樣式化可選字段 你可以使用 `:optional` 偽類來設置表單字段的樣式,例如 input、select 和 textarea,這些字段沒有 required 屬性。 ``` /* Selects all optional form fields on the page */ *:optional{ background-color: green; } ``` ## 19. 字間距屬性 使用 `word-spacing` 屬性指定單詞之間的空格長度。 ``` p { word-spacing: 1.245rem; } ``` ## 20. 建立漸變陰影 這就是您如何建立漸變陰影以獲得獨特的用戶體驗。 ``` :root{ --gradient: linear-gradient(to bottom right, crimson, coral); } div { height: 200px; width: 200px; background-image: var(--gradient); border-radius: 1rem; position: relative; } div::after { content: ""; position: absolute; inset: 0; background-image: var(--gradient); border-radius: inherit; filter: blur(25px) brightness(1.5); transform: translateY(15%) scale(0.95); z-index: -1; } ``` ![帶有漸變陰影的框](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7korhhx7zaj350nfzmyb.png) ## 21. 改變標題位置 使用 `caption-side` 屬性將表格標題(表格標題)放置在表格的指定一側。 ![從上到下更改表格標題側](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7t44rugi8gx3ksndq560.gif) ## 22. 建立文本列 使用列屬性為文本元素製作漂亮的列佈局。 ``` /* 🏛️ divide the content of the "p" element into 3 columns */ p{ column-count: 3; column-gap: 4.45rem; column-rule: 2px dotted crimson; } ``` ![css 提示和技巧詩](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y1ryft9s27y56el3ljx4.png) --- 以上分享,希望對您有幫助!