🔍 搜尋結果:signal

🔍 搜尋結果:signal

Docker 掌握:初學者和專業人士的全面指南

Docker 是一個功能強大的平台,可簡化輕量級、可移植容器中應用程式的建立、部署和管理。它允許開發人員將應用程式及其相依性打包到標準化單元中,以實現無縫開發和部署。 Docker 增強了不同環境之間的效率、可擴展性和協作,使其成為現代軟體開發和 DevOps 實踐的重要工具。 我們將深入研究 Docker 的各個方面,從安裝和配置到掌握映像、儲存、網路和安全性。 安裝與配置 ----- 下面給出了在 CentOS 和 Ubuntu 上安裝 Docker Community Edition (CE) 的基本指南。 **在 CentOS 上安裝 Docker CE** - 安裝所需的軟體包: `sudo yum install -y () device-mapper-persistent-data lvm2` - 新增 Docker CE yum 儲存庫: `sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo` - 安裝 Docker CE 軟體包: `sudo yum install -y docker-ce-18.09.5 docker-ce-cli-18.09.5 containerd.io` - 啟動並啟用 Docker 服務: `sudo systemctl 啟動 docker sudo systemctl 啟用 docker` 將使用者加入Docker群組,授予使用者執行Docker命令的權限。下次登入後它將可以存取 Docker。 `sudo usermod -a -G docker` **在 Ubuntu 上安裝 Docker CE** - 安裝所需的軟體包: `sudo apt-get 更新 sudo apt-get -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common` - 新增 Docker 儲存庫的 GNU Privacy Guard (GPG) 金鑰: `curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -` - 新增 Docker Ubuntu 儲存庫: `sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable` - 安裝包: `sudo apt-get install -y docker-ce=5:18.09.5~3-0~ubuntu-bionic docker-ce-cli=5:18.09.5~3-0~ubuntu-bionic containerd.io` 將使用者加入Docker群組,授予使用者執行Docker命令的權限。下次登入後它將可以存取 Docker。 `sudo usermod -a -G docker` **選擇儲存驅動程式** 儲存驅動程式是處理容器內部儲存的可插入驅動程式。 CentOS和Ubuntu系統的預設驅動程式是overlay2。 若要確定目前的儲存驅動程式: `docker info | grep "Storage"` 選擇不同儲存驅動程式的一種方法是將`--storage-driver`標誌傳遞給 Docker 守護程式。設定儲存驅動程式的建議方法是使用守護程式設定檔。 - 建立或編輯守護程序設定檔: `sudo vi /etc/docker/daemon.json` - 新增儲存驅動程式值: `"storage-driver": "overlay2"` 請記住在進行任何更改後重新啟動 Docker,然後檢查狀態。 `sudo systemctl 重新啟動 docker sudo systemctl 狀態泊塢窗` **執行容器** `docker run IMAGE[:TAG] [COMMAND] [ARGS]` `IMAGE` :指定執行容器的映像。 `COMMAND and ARGS` :在容器內執行指令。 `TAG` :指定影像標籤或版本 `-d` :以分離模式運作容器。 `--name NAME` :為容器指定一個指定的名稱,而不是通常隨機分配的名稱。 `--restart RESTART` :指定 Docker 何時自動重新啟動容器。 - `no (default)` :從不重新啟動容器。 - `on-failure` :僅當容器失敗時(以非零退出程式碼退出)。 - `always` :無論成功或失敗,始終重新啟動容器。 - `unless-stopped` :無論容器成功或失敗,始終重新啟動容器,並且在守護程序啟動時,除非手動停止容器。 `-p HOST_PORT` : CONTAINER\_PORT:發布容器的連接埠。 HOST\_PORT 是在主機上偵聽的端口,到該端口的流量將映射到容器上的 CONTAINER\_PORT。 `--memory MEMORY` :對記憶體使用設定硬性限制。 `--memory-reservation MEMORY` :設定記憶體使用的軟限制。 `docker run -d --name nginx --restart unless-stopped -p 8080:80 --memory 500M --memory-reservation 256M nginx:latest` 用於管理正在執行的容器的一些命令是: `docker ps` :列出正在執行的容器。 `docker ps -a` :列出所有容器,包括已停止的容器。 `docker container stop [alias: docker stop]` :停止正在運作的容器。 `docker container start [alias: docker start]` :啟動已停止的容器。 `docker container rm [alias: docker rm]` :刪除容器(必須先停止) **升級 Docker 引擎** 停止 Docker 服務: `sudo systemctl stop docker` 安裝所需版本的 docker-ce 和 docker-ce-cli: `sudo apt-get install -y docker-ce=<new version> docker-ce-cli=<new version>` 驗證目前版本 `docker version` 鏡像建立、管理和註冊 ---------- 鏡像是一個可執行包,包含執行容器所需的所有軟體。 使用映像執行容器: `docker run IMAGE` 下載圖片: `docker拉映像 docker鏡像拉取鏡像` 映像和容器使用分層檔案系統。每層僅包含與前一層的差異。 使用以下命令查看影像中的檔案系統層: `docker image history IMAGE` Dockerfile 是一個定義了一系列指令並用於建立映像的檔案。 ``` # Use the official Nginx base image FROM nginx:latest # Set an environment variable ENV MY_VAR=my_value # Copy custom configuration file to container COPY nginx.conf /etc/nginx/nginx.conf # Run some commands during the build process RUN apt-get update && apt-get install -y curl # Expose port 80 for incoming traffic EXPOSE 80 # Start Nginx server when the container starts CMD ["nginx", "-g", "daemon off;"] ``` 建構圖像: `docker build -t TAG_NAME DOCKERFILE_LOCATION` Dockerfile 指令: `FROM` :指定用於正在建置的 Docker 映像的基礎映像。它定義了映像的起點,可以是 Docker Hub 或私有註冊表上可用的任何有效映像。 `ENV` :設定影像內的環境變數。在建置過程和容器執行時可以存取這些變數。 `COPY or ADD` :將檔案和目錄從建置上下文(Dockerfile 所在的目錄)複製到映像中。 COPY 通常更適合簡單的文件複製,而 ADD 支援附加功能,例如解壓縮存檔。 `RUN` :在建置過程中執行指令。您可以使用 RUN 安裝依賴項、執行腳本或執行任何其他必要的任務。 `EXPOSE` :通知 Docker 容器將在執行時間監聽指定的網路連接埠。它不會將連接埠發佈到主機或使容器可以從外部存取。 `CMD or ENTRYPOINT` :指定從映像啟動容器時要執行的指令。 CMD 提供可以覆寫的預設參數,而 ENTRYPOINT 指定不能覆寫的指令。 `WORKDIR` :設定任何後續 RUN、CMD、ENTRYPOINT、COPY 或 ADD 指令的工作目錄。 `STOPSIGNAL` :設定將用於停止容器程序的自訂訊號。 `HEALTHCHECK` :設定 Docker 守護程式將使用的指令來檢查容器是否健康 Dockerfile 中的多階段建置是一種用於建立更有效率、更小的 Docker 映像的技術。它涉及在 Dockerfile 中定義多個階段,每個階段都有自己的一組指令和依賴項。 包含多階段建置定義的範例 Dockerfile 是: ``` # Build stage FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /app # Copy and restore project dependencies COPY *.csproj . RUN dotnet restore # Copy the entire project and build COPY . . RUN dotnet build -c Release --no-restore # Publish the application RUN dotnet publish -c Release -o /app/publish --no-restore # Runtime stage FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime WORKDIR /app COPY --from=build /app/publish . # Expose the required port EXPOSE 80 # Set the entry point for the application ENTRYPOINT ["dotnet", "YourApplication.dll"] ``` **管理影像** 影像管理的一些關鍵命令是: 列出系統上的影像: `docker image ls` 列出系統上的映像,包括中間映像: `docker image ls -a` 取得有關圖像的詳細資訊: `docker image inspect <IMAGE>` 刪除影像: `docker rmi docker 映像 rm docker 映像 rm -f ` 只有當沒有容器或其他圖像標籤引用圖像時,圖像才會被刪除。尋找並刪除懸空或未使用的圖像: `docker image prune` **Docker 註冊表** Docker 註冊表可作為儲存和共用 Docker 映像的集中儲存庫。 Docker Hub 是由 Docker 管理的預設、公開可用的註冊表。透過利用註冊表鏡像,我們可以免費設定和管理我們自己的私有註冊表。 執行一個簡單的註冊表: `docker run -d -p 5000:5000 --restart=always --name registry registry:2` 將圖像上傳到註冊表: `docker push <IMAGE>:<TAG>` 從註冊表下載映像: `docker pull <IMAGE>:<TAG>` 登入註冊表: `docker login REGISTRY_URL` 有兩種身份驗證方法可用於使用不受信任或自簽名憑證連接到私有註冊表: **安全性**:這涉及將註冊表的公共憑證新增至 /etc/docker/certs.d/ 目錄。 **Insecure** :此方法需要將登錄檔新增至 daemon.json 檔案中的 insecure-registries 清單中,或使用 --insecure-registry 標誌將其傳遞給 dockerd。 **儲存和磁碟區** 儲存驅動程式控制如何在 Docker 主機上儲存和管理映像和容器。 Docker 使用可插拔架構支援多種儲存驅動程式。 **overlay2** :所有 Linux 發行版的首選 **fusion-overlayfs** :僅適用於執行 Rootless Docker(不是 Ubuntu 或 Debian 10) **vfs** :用於測試目的,以及無法使用寫入時複製檔案系統的情況。 **儲存型號** \*\*檔案系統儲存:\*\* - 資料以常規檔案的形式儲存在主機磁碟上 - 有效利用記憶體 - 寫入繁重的工作負載效率低下 - overlay2使用 **區塊儲存:** - 使用特殊的區塊儲存設備將資料儲存在區塊中 - 高效率處理寫入繁重的工作負載 - 由 btrfs 和 zfs 使用 **物件儲存:** - 將資料儲存在外部基於物件的儲存中 - 應用程式必須設計為使用基於物件的儲存。 - 靈活且可擴展。 **配置overlay2儲存驅動** 停止 Docker 服務: `sudo systemctl stop docker` 建立或編輯守護程序設定檔: `sudo vi /etc/docker/daemon.json` 新增/編輯儲存驅動程式值: `"storage-driver": "overlay2"` 請記住在進行任何更改後重新啟動 Docker,然後檢查狀態。 `sudo systemctl 重新啟動 docker sudo systemctl 狀態泊塢窗` **Docker 卷** Docker 上有兩種不同類型的資料掛載: **Bind Mount** :將主機上的特定目錄掛載到容器。它對於在容器和主機之間共用設定檔和其他資料非常有用。 **命名磁碟區**:將目錄掛載到容器,但 Docker 動態控製磁碟區在磁碟上的位置。 在容器中新增綁定掛載或磁碟區有不同的語法: \_-v 語法 \_ 綁定安裝:來源以正斜線“/”開頭,這使其成為綁定安裝。 `docker run -v /opt/data:/tmp nginx` 命名卷:來源只是一個字串,這表示這是一個磁碟區。如果不存在具有所提供名稱的捲,它將自動建立。 `docker run -v my-vol:/tmp nginx` *--掛載語法* 綁定掛載: `docker run --mount source=/opt/data,destination=/tmp nginx` 命名卷: `docker run --mount source=my-vol,destination=/tmp nginx` 我們可以將相同的磁碟區掛載到多個容器,從而允許它們共享資料。我們也可以自己建立和管理卷,而無需執行容器。 一些常見且有用的指令: `docker volume create VOLUME` :建立一個磁碟區。 `docker volume ls` :列出卷。 `docker volume inspect VOLUME` :檢查卷。 `docker volume rm VOLUME` :刪除磁碟區。 **影像清理** 檢查Docker的磁碟使用情況: `docker system df` `docker system df -v` 刪除未使用或懸空的影像: `docker 映像修剪 docker映像修剪-a` Docker 網路 --------- Docker 容器網路模型 (CNM) 是一個概念模型,描述 Docker 網路的元件和概念。 Docker CNM 有多種實作: **沙箱**:一個隔離單元,包含與單一容器關聯的所有網路元件。 **端點**:將一個沙箱連接到一個網路。 **網路**:可以相互通訊的端點的集合。**網路驅動程式**:可插拔驅動程序,提供 CNM 的特定實作。 **IPAM 驅動程式**:提供 IP 位址管理。分配和指派 IP 位址。 **內建網路驅動程式** **Host** :此驅動程式將容器直接連接到主機的網路堆疊。它不提供容器之間或容器與主機之間的隔離。 `docker run --net host nginx` **Bridge** :此驅動程式使用虛擬橋接器介面在同一主機上執行的容器之間建立連線。 `docker 網路建立 --driver 橋 my-bridge-net docker run -d --network my-bridge-net nginx` **Overlay** :此驅動程式使用路由網格來連接多個 Docker 主機(通常在 Docker 群組中)的容器。 `docker 網路建立 --driver 覆蓋 my-overlay-net docker 服務建立 --network my-overlay-net nginx` **MACVLAN** :此驅動程式將容器直接連接到主機的網路接口,但使用特殊配置來提供隔離。 `docker網路建立-d macvlan --subnet 192.168.0.0/24 --gateway 192.168.0.1 -oparent=eth0 my-macvlan-net docker run -d --net my-macvlan-net nginx` **None** :此驅動程式提供沙箱隔離,但它不提供容器之間或容器與主機之間的網路的任何實作。 `docker run --net none -d nginx` **建立 Docker 橋接網絡** 它是預設驅動程式。因此,任何在未指定驅動程式的情況下建立的網路都將是橋接網路。 建立橋接網路。 `docker network create my-net` 在橋接網路上執行容器。 `docker run -d --network my-net nginx` 預設情況下,同一網路上的容器和服務只需使用容器或服務名稱即可相互通訊。 Docker 在網路上提供 DNS 解析,使其能夠正常運作。 提供網路別名以提供存取容器或服務的附加名稱。 `docker run -d --network my-net --network-alias my-nginx-alias nginx` 當必須與 Docker 網路互動時,一些有用的命令是: `docker network ls` :列出網路。 `docker network inspect NETWORK` :檢查網路。 `docker network connect CONTAINER NETWORK` :將容器連接到網路。 `docker network disconnect CONTAINER NETWORK` :斷開容器與網路的連接。 `docker network rm NETWORK` :刪除網路。 **建立 Docker 覆蓋網絡** 建立覆蓋網路: `docker network create --driver overlay NETWORK_NAME` 建立使用網路的服務: `docker service create --network NETWORK_NAME IMAGE` **網路故障排除** 查看容器日誌: `docker logs CONTAINER` 查看服務的所有任務的日誌: `docker service logs SERVICE` 查看Docker守護程序日誌: `sudo jounralctl -u docker` 我們可以使用nicolaka/netshoot鏡像來執行網路故障排除。它附帶了各種有用的網路相關工具。我們可以將一個容器注入另一個容器的網路沙箱中以進行故障排除。 `docker run --network container:CONTAINER_NAME nicolaka/netshoot` **配置 Docker 使用外部 DNS** 在 daemon.json 中為 Docker 容器設定係統範圍的預設 DNS: `{ “DNS”:\[“8.8.8.8”\] }` 為單一容器設定 DNS。 `docker run --dns 8.8.4.4 IMAGE` 安全 -- **簽署映像並啟用 Docker 內容信任** Docker Content Trust (DCT) 是一項功能,可讓我們在執行映像之前對映像進行簽名並驗證簽名。透過設定環境變數啟用 Docker Content Trust: `DOCKER_CONTENT_TRUST=1` 如果映像未簽署或在啟用 Docker Content Trust 的情況下簽章無效,系統將不會運作映像。 使用以下命令簽署並推送映像: `docker trust sign` 當 DOCKER\_CONTENT\_TRUST=1 時,docker push 在推送之前會自動對映像進行簽署。 **預設 Docker 引擎安全性** 基本的 Docker 安全性概念: Docker 使用命名空間將容器程序彼此隔離以及與主機隔離。這可以防止攻擊者在設法獲得對一個容器的控制時影響或獲得對其他容器或主機的控制。 Docker 守護程式必須以 root 存取權限執行。在允許任何人與守護進程互動之前,請注意這一點。它可用於存取整個主機。 Docker 利用 Linux 功能為容器程序分配精細權限。例如,偵聽低埠(低於 1024)通常需要進程以 root 身分執行,但 Docker 使用 Linux 功能允許容器偵聽連接埠 80,而無需以 root 身分執行。 **保護 Docker 守護程式 HTTP 套接字的安全** 為 Docker 伺服器產生憑證授權單位和伺服器憑證。 ``` openssl genrsa -aes256 -out ca-key.pem 4096` `openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem -subj "/C=US/ST=Texas/L=Keller/O=Linux Academy/OU=Content/CN=$HOSTNAME" openssl genrsa -out server-key.pem 4096 ` `openssl req -subj "/CN=$HOSTNAME" -sha256 -new -key server-key.pem -out server.csr \ echo subjectAltName = DNS:$HOSTNAME,IP:,IP:127.0.0.1 >> extfile.cnf ` `echo extendedKeyUsage = serverAuth >> extfile.cnf ` `openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf` Generate client certificates: `openssl genrsa -out key.pem 4096 openssl req -subj '/CN=client' -new -key key.pem -out client.csr echo extendedKeyUsage = clientAuth > extfile-client.cnf openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \ -CAcreateserial -out cert.pem -extfile extfile-client.cnf ``` 對憑證文件設定適當的權限: `chmod -v 0400 ca-key.pem key.pem server-key.pem chmod -v 0444 ca.pem server-cert.pem cert.pem` 將 Docker 主機配置為使用 tlsverify 模式以及先前建立的憑證: ``` sudo vi /etc/docker/daemon.json { "tlsverify": true, "tlscacert": "/home/user/ca.pem", "tlscert": "/home/user/server-cert.pem", "tlskey": "/home/user/server-key.pem" } ``` 編輯 Docker 服務文件,尋找以 ExecStart 開頭的行並更改 -H。 `sudo vi /lib/systemd/system/docker.service` `ExecStart=/usr/bin/dockerd -H=0.0.0.0:2376 --containerd=/run/containerd/containerd.sock` `sudo systemctl daemon-reload` `sudo systemctl restart docker` 將 CA 憑證和用戶端憑證檔案複製到客戶端電腦。 在用戶端電腦上,設定用戶端以安全地連線到遠端 Docker 守護程式: `mkdir -pv ~/.docker` `cp -v {ca,cert,key}.pem ~/.docker` `export DOCKER_HOST=tcp://:2376 DOCKER_TLS_VERIFY=1` 測試連接: `docker version` 結論 -- 總而言之,掌握 Docker 可以簡化安裝、設定、映像管理、儲存、網路和安全性,從而改變您的開發工作流程。本指南為您提供必要的知識和實務技能,使您能夠有效率地建立、發布和執行應用程式。利用 Docker 的強大功能將您的容器管理提升到一個新的水平。 --- 原文出處:https://dev.to/theyasirr/docker-mastery-a-comprehensive-guide-for-beginners-and-pros-2p18

每個開發人員都需要了解的 300 多個免費 API

目錄 == 1. [天氣 API ⛅️🌦️🌩️](#weather-apis) 2. [匯率 API 💱💲💹](#exchange-rates-apis) 3. [加密貨幣 API ₿💰🔗](#cryptocurrency-apis) 4. [佔位符圖像 API 📸🖼️🎨](#placeholder-image-apis) 5. [隨機產生器 API 🎲🔀🎰](#random-generators-apis) 6. [新聞 API 📰📢🗞️](#news-apis) 7. [地圖與地理定位 API 🗺️📍🌍](#maps-and-geolocation-apis) 8. [搜尋 API 🔍📑🕵️](#search-apis) 9. [機器學習 API 🤖🧠🔮](#machine-learning-apis) 10. [截圖與圖片 API 📷🌐🖼️](#screenshot-and-picture-apis) 11. [SEO API 🔍📈💡](#seo-apis) 12. [購物 API 🛍️🛒📦](#shopping-apis) 13. [開發者 API 💻🔧🛠️](#developer-apis) 14. [旅行和交流 API 🛫🚗🚉](#travel-and-transportation-apis) 15. [通訊 API 📞💬📧](#communication-apis) 16. [支付和金融 API 💳💸🏦](#payment-and-financial-apis) 17. [分析與監控 API 📊📈📉](#analytics-and-monitoring-apis) 18. [自然語言處理 (NLP) API 🗣️🔍💬](#natural-language-processing-nlp-apis) 19. [實用程式和工具 API 🛠️🔧⚙️](#utilities-and-tools-apis) 20. [政府和開放資料 API 🏛️📜📊](#government-and-open-data-apis) [Qit.tools](https://qit.tools/) - ⚡ 互動式線上網路 🛠️ 工具 --- 天氣 API ⛅️🌦️🌩️ ------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |打開天氣地圖 |全球天氣資料,包括預報和當前天氣 | 60 次通話/分鐘 | API 金鑰 |[連結](https://openweathermap.org/api)| |天氣堆疊 |即時與歷史天氣資料 |每月 1000 通電話 | API 金鑰 |[連結](https://weatherstack.com/documentation)| |天氣比特 |天氣預報資料,包括預報和當前天氣 |每天 500 通電話 | API 金鑰 |[連結](https://www.weatherbit.io/api)| |克利馬塞爾|超本地天氣資料與見解 |每天 100 通電話 | API 金鑰 |[連結](https://docs.climacell.co/)| |準確天氣 |天氣預報|每天 50 通電話 | API 金鑰 |[連結](https://developer.accuweather.com/apis)| |視覺穿越|歷史和當前天氣資料|每天 1000 通電話 | API 金鑰 |[連結](https://www.visualcrossing.com/weather-api)| | 2020 年天氣 |天氣預報 |每天 100 通電話 | API 金鑰 |[連結](https://www.weather2020.com/weather-api/)| |風暴玻璃|海洋氣象資料|每天 50 通電話 | API 金鑰 |[連結](https://stormglass.io/docs/)| |天氣 API |天氣預報資料,包括預報和當前天氣 |每月 1000 通電話 | API 金鑰 |[連結](https://www.weatherapi.com/docs/)| | Aeris 天氣 |天氣資料和影像|每月 1000 通電話 | API 金鑰 |[連結](https://www.aerisweather.com/support/docs/api/)| |這裡 天氣 |天氣預報資料,包括預報和當前天氣 |每月 25 萬通電話 | API 金鑰 |[連結](https://developer.here.com/documentation/weather/dev_guide/index.html)| |世界天氣在線|全球天氣資料,包括預報和歷史天氣|每天 500 通電話 | API 金鑰 |[連結](https://www.worldweatheronline.com/developer/)| |明天.io |超本地天氣資料與見解 |每天 100 通電話 | API 金鑰 |[連結](https://docs.tomorrow.io/)| |黑暗的天空|天氣預報資料,包括預報和當前天氣 |每天 1000 通電話 | API 金鑰 |[連結](https://darksky.net/dev)| |國家氣象局|美國政府天氣資料|無限 |無 |[連結](https://www.weather.gov/documentation/services-web-api)| --- 匯率 API 💱💲💹 ---------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |匯率-API | 160 種貨幣的準確匯率 |每月 1500 通電話 | API 金鑰 |[連結](https://www.exchangerate-api.com/docs)| |開放匯率|即時與歷史匯率 |每月 1000 通電話 | API 金鑰 |[連結](https://docs.openexchangerates.org/)| |貨幣層 | 168 種世界貨幣即時匯率 |每月 1000 通電話 | API 金鑰 |[連結](https://currencylayer.com/documentation)| |固定器|即時匯率與貨幣換算|每月 1000 通電話 | API 金鑰 |[連結](https://fixer.io/documentation)| | XE 貨幣資料 |即時與歷史匯率 |每月 1000 通電話 | API 金鑰 |[連結](https://xecdapi.xe.com/)| |外匯匯率 API |即時與歷史外匯匯率 |每月 1000 通電話 | API 金鑰 |[連結](https://www.forexrateapi.com/documentation)| |費率API |免費外匯匯率和貨幣兌換|無限|無 |[連結](https://ratesapi.io/documentation/)| |匯率API | 160 種貨幣的準確匯率 |每月 1500 通電話 | API 金鑰 |[連結](https://www.exchangerate-api.com/docs)| | OANDA 匯率 |即時與歷史匯率 |每月 1000 通電話 | API 金鑰 |[連結](https://www.oanda.com/fx-for-business/fx-data-services)| |貨幣轉換器 API |即時匯率與貨幣換算 |每月 1000 通電話 | API 金鑰 |[連結](https://www.currencyconverterapi.com/docs)| |匯率API |匯率與貨幣換算|每月 1000 通電話 | API 金鑰 |[連結](https://www.exchangeratesapi.io/documentation)| |阿爾法優勢|即時與歷史匯率 |每天 500 通電話 | API 金鑰 |[連結](https://www.alphavantage.co/documentation/)| |西點燃|外匯匯率API |每月 1000 通電話 | API 金鑰 |[連結](https://www.xignite.com/xforex-rates)| | Everbase 貨幣 |匯率與貨幣換算|每月 1000 通電話 | API 金鑰 |[連結](https://currency-api.everbase.com/documentation)| |匯率主機 |外匯匯率API |無限|無 |[連結](https://exchangerate.host/#/#docs)| --- 加密貨幣 API ₿💰🔗 ------------ |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| | CoinGecko | 幣虎超過 6000 種貨幣的加密貨幣資料 |無限|無 |[連結](https://www.coingecko.com/en/api/documentation)| | CoinMarketCap |加密貨幣市值排名、圖表等 |每天 333 通電話 | API 金鑰 |[連結](https://coinmarketcap.com/api/documentation/)| |加密貨幣比較 |加密貨幣資料與價格比較 |每月 25 萬通電話 | API 金鑰 |[連結](https://min-api.cryptocompare.com/documentation)| |辣椒粉 |加密貨幣市場資料|每月 25,000 通電話 | API 金鑰 |[連結](https://api.coinpaprika.com)| |經濟學 |加密貨幣市值和定價資料|每月 125,000 通電話 | API 金鑰 |[連結](https://nomics.com/docs/)| |幣API |即時與歷史加密貨幣資料 |每月 100,000 通電話 | API 金鑰 |[連結](https://docs.coinapi.io/)| |梅薩裡 |加密貨幣資料與研究 |每天 1000 通電話 | API 金鑰 |[連結](https://messari.io/api)| |硬幣傳說 |加密貨幣市場資料 |無限|無 |[連結](https://www.coinlore.com/cryptocurrency-data-api)| |幣庫 |加密貨幣資料,包括價格和市值 |每天 100 個請求 | API 金鑰 |[連結](https://coinlib.io/apidocs)| | Bitfinex |加密貨幣交易平台API |無限|無 |[連結](https://docs.bitfinex.com/docs)| |比特雷克斯 |加密貨幣交易平台API |無限|無 |[連結](https://bittrex.github.io/api/v3)| |幣安 |加密貨幣交易平台API |無限|無 |[連結](https://binance-docs.github.io/apidocs/spot/en/)| |庫幣 |加密貨幣交易平台API |無限|無 |[連結](https://docs.kucoin.com/)| |克拉肯 |加密貨幣交易平台API |無限|無 |[連結](https://www.kraken.com/features/api)| |波蘭 |加密貨幣交易平台API |無限|無 |[連結](https://docs.poloniex.com/)| --- 佔位符圖像 API 📸🖼️🎨 -------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |洛雷姆·皮克蘇姆 |隨機佔位符圖像 |無限|無 |[連結](https://picsum.photos/)| |佔位符.com |自訂佔位符影像 |無限|無 |[連結](https://placeholder.com/)| | Unsplash 來源 |高品質佔位符影像 |無限|無 |[連結](https://source.unsplash.com/)| |放置小貓 |小貓的佔位圖像 |無限|無 |[連結](https://placekitten.com/)| |地點狗 |狗的佔位符圖像 |無限|無 |[連結](https://place.dog/)| |占星者 |熊的佔位符影像 |無限|無 |[連結](https://placebear.com/)| |填充穆雷 |比爾·莫瑞 (Bill Murray) 的佔位符圖像 |無限|無 |[連結](http://www.fillmurray.com/)| | FakerAPI |虛假資料和占位符圖像 |無限|無 |[連結](https://fakerapi.it/en)| |虛擬圖像.com |自訂佔位符影像 |無限|無 |[連結](https://dummyimage.com/)| | ImagePlaceholder.com |自訂佔位符影像 |無限|無 |[連結](https://imageplaceholder.com/)| |佔位符影像 |帶有自訂文字的佔位符圖像 |無限|無 |[連結](https://placeholderimage.dev/)| | Picsum.照片 |來自 Unsplash 的隨機圖像 |無限|無 |[連結](https://picsum.photos/)| |隨機影像API |隨機佔位符圖像 |無限|無 |[連結](https://random.imagecdn.app/)| |普拉霍爾德.it |自訂佔位符影像 |無限|無 |[連結](https://placehold.it/)| | LoremFlickr |隨機佔位符圖像 |無限|無 |[連結](https://loremflickr.com/)| --- 隨機產生器 API 🎲🔀🎰 ------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |隨機.org |真隨機數生成| 1,000,000 位/天 | API 金鑰 |[連結](https://www.random.org/)| |隨機用戶 |產生隨機用戶資料 |無限|無 |[連結](https://randomuser.me/)| | FakerAPI |虛假資料生成 |無限|無 |[連結](https://fakerapi.it/en)| | UUID 產生器 |產生隨機 UUID |無限|無 |[連結](https://www.uuidgenerator.net/)| |骰子熊頭像 |產生隨機頭像 |無限|無 |[連結](https://avatars.dicebear.com/)| |密碼產生器 |產生隨機密碼 |無限|無 |[連結](https://passwordwolf.com/api/)| |貓的事實|隨機貓的事實|無限|無 |[連結](https://catfact.ninja/)| |有趣的翻譯 |生成有趣的翻譯 |每天 5 個請求 |無 |[連結](https://funtranslations.com/api)| |行情.休息 |產生隨機報價 | 10 個請求/小時 |無 |[連結](https://quotes.rest/)| |通知單|隨機建議生成器 |無限|無 |[連結](https://api.adviceslip.com/)| |無聊API |活動建議 |無限|無 |[連結](https://www.boredapi.com/)| |非常感謝產生隨機佔位符文字 |無限|無 |[連結](https://loripsum.net/)| |烏納梅斯 |產生隨機名稱 |無限|無 |[連結](https://uinames.com/)| |皮普|產生隨機人物檔案 |無限|無 |[連結](https://pipl.ir/)| |隨機資料API |產生隨機資料進行測試 |無限|無 |[連結](https://random-data-api.com/)| --- 新聞 API 📰📢🗞️ ----------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |新聞API |聚合各種來源的新聞文章 |每天 500 通電話 | API 金鑰 |[連結](https://newsapi.org/docs)| |當前 API |即時新聞資料 |每月 1000 通電話 | API 金鑰 |[連結](https://currentsapi.services/en/docs/)| |上下文網路新聞 |即時新聞搜尋與發現|每月 10,000 通電話 | API 金鑰 |[連結](https://rapidapi.com/contextualwebsearch/api/web-search)| |必應新聞搜尋 |微軟Bing的新聞搜尋結果|每月 3000 通電話 | API 金鑰 |[連結](https://docs.microsoft.com/en-us/azure/cognitive-services/bing-news-search/)| |媒體堆疊 |即時新聞資料 |每月 500 通電話 | API 金鑰 |[連結](https://mediastack.com/documentation)| |紐約時報 API |造訪《紐約時報》文章與檔案 |無限| API 金鑰 |[連結](https://developer.nytimes.com/apis)| |守護者API |造訪《衛報》文章與檔案 |無限| API 金鑰 |[連結](https://open-platform.theguardian.com/documentation/)| |活動登記|即時新聞與事件資料 |每月 500 通電話 | API 金鑰 |[連結](https://eventregistry.org/documentation)| | GDELT 專案 |即時事件資料與新聞 |每月 10,000 通電話 | API 金鑰 |[連結](https://blog.gdeltproject.org/gdelt-2-0-our-global-world-in-realtime/)| |新聞資料.io |來自各種來源的即時新聞文章 |每天 200 通電話 | API 金鑰 |[連結](https://newsdata.io/docs)| |上下文網路|根據上下文搜尋新聞文章 |每月 1000 通電話 | API 金鑰 |[連結](https://contextualwebsearch.com/news-api)| |我的新聞 API |存取各種新聞來源|每月 500 通電話 | API 金鑰 |[連結](https://mynewsapi.com/documentation)| | Webz.io |即時新聞與部落格資料 |每月 1000 通電話 | API 金鑰 |[連結](https://webz.io/documentation)| | AYLIEN 新聞 API |各種來源的新聞文章及分析 |每天 200 通電話 | API 金鑰 |[連結](https://newsapi.aylien.com/docs)| |駭客新聞 |存取黑客新聞文章 |無限|無 |[連結](https://github.com/HackerNews/API)| --- 地圖和地理定位 API 🗺️📍🌍 ---------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |谷歌地圖 API |全面的地圖和地理定位資料|每月 200 美元免費使用| API 金鑰 |[連結](https://developers.google.com/maps/documentation)| |地圖盒 |客製化地圖和地理定位服務|每月 50,000 次瀏覽 | API 金鑰 |[連結](https://docs.mapbox.com/)| | OpenCage 地理編碼 |正向和反向地理編碼 |每天 2,500 通電話 | API 金鑰 |[連結](https://opencagedata.com/api)| |這裡 地圖 |地圖和位置資料服務|每月 25 萬通電話 | API 金鑰 |[連結](https://developer.here.com/documentation)| |打開街道地圖 |免費可編輯的世界地圖|無限|無 |[連結](https://operations.osmfoundation.org/policies/nominatim/)| |位置堆疊 |用於正向和反向地理編碼的地理編碼 API |每月 25,000 通電話 | API 金鑰 |[連結](https://positionstack.com/documentation)| |湯姆湯姆 |地圖和地理定位資料服務|每天 2,500 通電話 | API 金鑰 |[連結](https://developer.tomtom.com/)| |地圖探索 |地圖和地理定位資料服務|每月 15,000 通電話 | API 金鑰 |[連結](https://developer.mapquest.com/documentation/)| | ipstack| IP地理定位API |每月 10,000 通電話 | API 金鑰 |[連結](https://ipstack.com/documentation)| |地理資訊 |地理編碼和反向地理編碼|每天 2,500 通電話 | API 金鑰 |[連結](https://www.geocod.io/)| |位置智商 |地理編碼和反向地理編碼|每天 5,000 通電話 | API 金鑰 |[連結](https://locationiq.com/docs)| |地圖繪製器 |地圖、地理編碼與地理定位服務 |每月 100,000 個切片請求 | API 金鑰 |[連結](https://www.maptiler.com/cloud/)| |什麼三字 |使用三字位址的定位服務 |每月 1000 通電話 | API 金鑰 |[連結](https://what3words.com/products)| |聰明街道 |地址驗證與地理編碼 |每月 250 個請求 | API 金鑰 |[連結](https://smartystreets.com/docs)| |地理化|地理編碼、路由和其他定位服務 |每月 30,000 個請求| API 金鑰 |[連結](https://apidocs.geoapify.com/)| --- 搜尋 API 🔍📑🕵️ ----------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |谷歌自訂搜尋|搜尋網路或特定網站 |每天 100 次查詢 | API 金鑰 |[連結](https://developers.google.com/custom-search/v1/overview)| |阿爾戈利亞 |快速、可靠的搜尋即服務 | 10,000 筆記錄 | API 金鑰 |[連結](https://www.algolia.com/doc/)| |必應搜尋 API |微軟Bing的搜尋結果|每月 3,000 通電話 | API 金鑰 |[連結](https://docs.microsoft.com/en-us/azure/cognitive-services/bing-web-search/)| |彈性搜尋|基於Lucene的搜尋引擎|免費套餐可用 | API 金鑰 |[連結](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html)| |斯威夫類型 |為您的網站客製化搜尋引擎 |每月 1000 個請求 | API 金鑰 |[連結](https://swiftype.com/documentation)| |美麗搜尋 |快速、開源搜尋引擎 |無限|無 |[連結](https://docs.meilisearch.com/)| |新增搜尋 |為您的網站客製化搜尋 |每天 50 次搜尋 | API 金鑰 |[連結](https://www.addsearch.com/docs/)| | Yandex 搜尋 API |使用 Yandex 搜尋網路 |每天 10,000 個請求 | API 金鑰 |[連結](https://yandex.com/dev/search/)| |雅虎搜尋 |使用 Yahoo | 搜尋網絡每天 5,000 次查詢 | API 金鑰 |[連結](https://developer.yahoo.com/boss/search/)| |沃爾夫拉姆·阿爾法 |計算知識引擎|每月 2,000 次查詢 | API 金鑰 |[連結](https://products.wolframalpha.com/api/documentation/)| |上下文網路搜尋|具有上下文過濾功能的網路搜尋 |每月 10,000 通電話 | API 金鑰 |[連結](https://rapidapi.com/contextualwebsearch/api/web-search)| |網站搜尋 360 |搜尋您的網站或應用程式 |每月 1,500 個請求 | API 金鑰 |[連結](https://www.sitesearch360.com/docs/)| | DuckDuckGo API |匿名搜尋網路 |無限|無 |[連結](https://duckduckgo.com/api)| |搜尋.io |搜尋即服務 | 1000 次操作/月| API 金鑰 |[連結](https://search.io/docs)| |阿帕奇·索爾 |高度可靠、可擴展的搜尋平台 |開源|無 |[連結](https://solr.apache.org/guide/)| --- 機器學習 API 🤖🧠🔮 ------------ |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |谷歌雲端機器學習 |機器學習服務與 API | $300 免費贈金 | API 金鑰 |[連結](https://cloud.google.com/products/ai)| |亞馬遜 SageMaker |建置、訓練與部署機器學習模型 |免費套餐可用 | API 金鑰 |[連結](https://aws.amazon.com/sagemaker/)| | IBM 沃森 |人工智慧和機器學習服務 |免費套餐可用 | API 金鑰 |[連結](https://www.ibm.com/watson/products-services/)| |微軟 Azure 機器學習 |機器學習服務與 API | $200 免費贈金 | API 金鑰 |[連結](https://azure.microsoft.com/en-us/services/machine-learning/)| |擁抱臉|最先進的 NLP 模型和 API |免費套餐可用 | API 金鑰 |[連結](https://huggingface.co/docs)| |開放人工智慧 |包括 GPT-3 在內的 AI 模型 |免費套餐可用 | API 金鑰 |[連結](https://beta.openai.com/docs/)| | BigML |機器學習平台與 API |免費套餐可用 | API 金鑰 |[連結](https://bigml.com/)| |克拉里法伊 |影像影片辨識服務|免費套餐可用 | API 金鑰 |[連結](https://docs.clarifai.com/)| |資料機器人|機器學習模型部署與管理 |免費套餐可用 | API 金鑰 |[連結](https://www.datarobot.com/)| |猴子學習 |文字分析與機器學習 |每月 300 次查詢 | API 金鑰 |[連結](https://monkeylearn.com/api/)| |艾琳|自然語言處理與機器學習 |免費套餐可用 | API 金鑰 |[連結](https://aylien.com/text-api/)| |演算法|演算法市場與機器學習 API |每月 10,000 次查詢 | API 金鑰 |[連結](https://algorithmia.com/developers)| |法術|機器學習基礎設施和工具|免費套餐可用 | API 金鑰 |[連結](https://spell.run/docs)| |海王星.ai |機器學習模型管理與監控 |免費套餐可用 | API 金鑰 |[連結](https://neptune.ai/)| |維茲.ai |自訂機器學習模型建立 |免費套餐可用 | API 金鑰 |[連結](https://vize.ai/)| --- 截圖與圖片 API 📷🌐🖼️ -------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |截圖API |抓取網站截圖 | 100 個螢幕截圖/月| API 金鑰 |[連結](https://screenshotapi.net/documentation)| |網址框 |擷取螢幕截圖並將網頁轉換為 PDF |每月 100 次捕獲 | API 金鑰 |[連結](https://urlbox.io/docs)| |第2頁圖片 |網頁截圖| 1000 個螢幕截圖/月| API 金鑰 |[連結](https://www.page2images.com/)| |縮網 |擷取網頁的螢幕截圖和縮圖 |每月 1000 次捕獲 | API 金鑰 |[連結](https://www.shrinktheweb.com/)| |瀏覽 |抓取網站截圖 | 1000 點/月 | API 金鑰 |[連結](https://browshot.com/api/documentation)| |縮圖.ws |抓取網站截圖 |每月 500 個螢幕截圖| API 金鑰 |[連結](https://thumbnail.ws/)| |網址框 |抓取網站截圖 |每月 1000 次捕獲 | API 金鑰 |[連結](https://www.urlbox.io/)| |截圖圖層 |抓取網站截圖 |每月 100 次捕獲 | API 金鑰 |[連結](https://screenshotlayer.com/documentation)| | APIFlash |抓取網站截圖 | 100 個螢幕截圖/月| API 金鑰 |[連結](https://apiflash.com/documentation)| | AbstractAPI 截圖 |抓取網站截圖 | 100 個螢幕截圖/月| API 金鑰 |[連結](https://www.abstractapi.com/website-screenshot-api)| |斯內皮托 |抓取網站截圖 |每月 100 次捕獲 | API 金鑰 |[連結](https://snapito.com/)| |網站2PDF |將網頁轉換為 PDF |每月 100 次捕獲 | API 金鑰 |[連結](https://website2pdf.io/)| |截圖機 |抓取網站截圖 | 1000 個螢幕截圖/月| API 金鑰 |[連結](https://www.screenshotmachine.com/)| |斯蒂利奧 |自動網站截圖|每月 1000 次捕獲 | API 金鑰 |[連結](https://stillio.com/)| |寶石像素 |抓取網站截圖 |每月 100 次捕獲 | API 金鑰 |[連結](https://www.gempixel.com/)| --- SEO API 🔍📈💡 ----------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |莫茲 | SEO 指標與資料 |每月 100 個請求 | API 金鑰 |[連結](https://moz.com/products/api)| |阿雷夫斯 | SEO 指標與資料 | 500 行/月 | API 金鑰 |[連結](https://ahrefs.com/api)| | SEMrush | SEO 指標與資料 |每月 100 個請求 | API 金鑰 |[連結](https://www.semrush.com/api/)| | Serpstat | SEO 指標與資料 |每天 1000 次查詢 | API 金鑰 |[連結](https://serpstat.com/api/)| |間諜福| SEO 指標與競爭對手分析 |每月 500 個請求 | API 金鑰 |[連結](https://www.spyfu.com/api)| | SEO 資料 |關鍵字、SERP 等的 SEO 資料 |每月 100 個請求 | API 金鑰 |[連結](https://docs.dataforseo.com/)| |認知SEO | SEO 指標與資料 |每月 1000 個請求 | API 金鑰 |[連結](https://cognitiveseo.com/api/)| |雄偉| SEO 指標與資料 |每月 100 個請求 | API 金鑰 |[連結](https://developer.majestic.com/)| |搜尋引擎結果頁面 API |即時搜尋引擎結果 |每月 1000 個請求 | API 金鑰 |[連結](https://serpapi.com/)| | RankRanger | SEO 指標與排名追蹤 |每月 1000 個請求 | API 金鑰 |[連結](https://www.rankranger.com/api)| |流動性| SEO 指標與資料 |每月 1000 個請求 | API 金鑰 |[連結](https://seobility.net/en/api/)| |光明本地|本地 SEO 資料和指標 |每月 1000 個請求 | API 金鑰 |[連結](https://www.brightlocal.com/api/)| |搜尋指標 | SEO 指標與資料 |每月 1000 個請求 | API 金鑰 |[連結](https://www.searchmetrics.com/api/)| |統計 |即時搜尋引擎結果 |每月 1000 個請求 | API 金鑰 |[連結](https://getstat.com/api/)| |林迪|反向連結檢查器和 SEO 指標 |每月 1000 個請求 | API 金鑰 |[連結](https://www.linkody.com/api)| --- 購物 API 🛍️🛒📦 ----------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |亞馬遜產品廣告API |存取亞馬遜產品資料 |每月 1,000 個請求 | API 金鑰 |[連結](https://webservices.amazon.com/paapi5/documentation)| |易趣 API |存取 eBay 產品資料和市場 |每天 5,000 個請求 | API 金鑰 |[連結](https://developer.ebay.com/api-docs/static/apis.html)| |沃爾瑪API |存取沃爾瑪產品資料和市場 |每天 5,000 個請求 | API 金鑰 |[連結](https://developer.walmart.com/)| |百思買 API |存取百思買產品資料 |每天 5,000 個請求 | API 金鑰 |[連結](https://developer.bestbuy.com/)| | Etsy API |存取 Etsy 產品資料和市場 |每天 5,000 個請求 | API 金鑰 |[連結](https://www.etsy.com/developers/documentation)| |樂天 API |存取樂天產品資料和市場 |每天 5,000 個請求 | API 金鑰 |[連結](https://webservice.rakuten.co.jp/documentation/)| | Shopify API |存取 Shopify 商店資料和市場 |無限| API 金鑰 |[連結](https://shopify.dev/api)| | WooCommerce API |存取 WooCommerce 商店資料和市場 |無限| API 金鑰 |[連結](https://woocommerce.github.io/woocommerce-rest-api-docs/)| | BigCommerce API |存取 BigCommerce 商店資料和市場 |無限| API 金鑰 |[連結](https://developer.bigcommerce.com/api-reference)| |速賣通 API |存取 AliExpress 產品資料和市場 |每天 1,000 個請求 | API 金鑰 |[連結](https://developers.aliexpress.com/en/doc.htm)| |扎蘭多 API |存取 Zalando 產品資料和市場 |每天 5,000 個請求 | API 金鑰 |[連結](https://developers.zalando.com/)| |目標API |存取 Target 產品資料和市場 |每天 1,000 個請求 | API 金鑰 |[連結](https://developer.target.com/)| | Flipkart API |存取 Flipkart 產品資料和市場 |每天 5,000 個請求 | API 金鑰 |[連結](https://affiliate.flipkart.com/api-docs)| |好市多 API |存取 Costco 產品資料和市場 |每天 5,000 個請求 | API 金鑰 |[連結](https://costco.com/)| |家得寶 API |存取家得寶產品資料和市場 |每天 5,000 個請求 | API 金鑰 |[連結](https://developer.homedepot.com/)| --- 開發者 API 💻🔧🛠️ ------------ |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| | GitHub API |存取 GitHub 資料 |無限| OAuth |[連結](https://docs.github.com/en/rest)| |亞搏體育appGitLab API |存取 GitLab 資料 |無限| OAuth |[連結](https://docs.gitlab.com/ee/api/)| | Bitbucket API |存取 Bitbucket 資料 |無限| OAuth |[連結](https://developer.atlassian.com/bitbucket/api/2/reference/)| |特拉維斯 CI API |存取 Travis CI 資料 |無限| API 金鑰 |[連結](https://developer.travis-ci.com/)| |詹金斯 API |存取 Jenkins 資料 |無限| API 金鑰 |[連結](https://www.jenkins.io/doc/book/using/remote-access-api/)| | CircleCI API |存取 CircleCI 資料 |無限| API 金鑰 |[連結](https://circleci.com/docs/api/v2/)| | GitKraken API |存取 GitKraken 資料 |無限| API 金鑰 |[連結](https://support.gitkraken.com/developers/)| | Heroku API |存取 Heroku 資料和服務 |無限| OAuth |[連結](https://devcenter.heroku.com/articles/platform-api-reference)| |維塞爾 API |存取 Vercel 資料和服務 |無限| API 金鑰 |[連結](https://vercel.com/docs/api)| | Netlify API |存取 Netlify 資料和服務 |無限| OAuth |[連結](https://docs.netlify.com/api/get-started/)| | Firebase API |存取 Firebase 資料和服務 |無限| API 金鑰 |[連結](https://firebase.google.com/docs/reference/rest)| |數位海洋 API |存取 DigitalOcean 資料與服務 |無限| OAuth |[連結](https://developers.digitalocean.com/documentation/v2/)| |亞馬遜AWS官方博客存取AWS資料和服務|免費套餐可用 | API 金鑰 |[連結](https://docs.aws.amazon.com/)| | Azure API |存取 Azure 資料和服務 |免費套餐可用 | API 金鑰 |[連結](https://docs.microsoft.com/en-us/azure/azure-api-management/)| | Google雲端API |存取 Google Cloud 資料與服務 | $300 免費贈金 | API 金鑰 |[連結](https://cloud.google.com/apis)| --- 旅行和交流 API 🛫🚗🚉 ------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |天巡 API |存取航班搜尋和預訂資料 |每天 500 個請求 | API 金鑰 |[連結](https://developers.skyscanner.net/docs)| |艾瑪迪斯 API |存取旅行預訂和搜尋資料 |每天 500 通電話 | API 金鑰 |[連結](https://developers.amadeus.com/)| |谷歌航班 API |存取航班搜尋和預訂資料 |每天 1000 個請求 | API 金鑰 |[連結](https://developers.google.com/flights)| | Rome2Rio API |取得多式聯運旅行搜尋資料 |每天 1000 個請求 | API 金鑰 |[連結](https://www.rome2rio.com/documentation/search)| |軍刀 API |存取旅遊預訂和搜尋資料 |每天 500 個請求 | API 金鑰 |[連結](https://developer.sabre.com/docs/read/rest_apis)| |皮划艇 API |存取航班和酒店搜尋資料 |每天 500 個請求 | API 金鑰 |[連結](https://developer.kayak.com/)| | Expedia API |存取旅行預訂和搜尋資料 |每天 500 個請求 | API 金鑰 |[連結](https://developers.expediagroup.com/docs/apis)| | Priceline API |存取旅行預訂和搜尋資料 |每天 500 個請求 | API 金鑰 |[連結](https://developer.priceline.com/docs/apis)| | TripAdvisor API |存取旅遊評論和搜尋資料 |每天 500 個請求 | API 金鑰 |[連結](https://developer-tripadvisor.com/home/docs)| |愛彼迎 API |取得短期租賃資料 |每天 500 個請求 | API 金鑰 |[連結](https://developer.airbnb.com/docs)| | Lyft API |取得共乘資料 |每天 1000 個請求 | API 金鑰 |[連結](https://developer.lyft.com/docs)| |優步 API |取得共乘資料 |每天 1000 個請求 | API 金鑰 |[連結](https://developer.uber.com/docs)| | BlaBlaCar API |取得共乘資料 |每天 500 個請求 | API 金鑰 |[連結](https://dev.blablacar.com/docs)| | Yelp API |存取業務和評論資料 |每天 5000 個請求 | API 金鑰 |[連結](https://www.yelp.com/developers/documentation/v3)| |運輸API |取得公共交通資料 |每天 1000 個請求 | API 金鑰 |[連結](https://developer.transportapi.com/docs)| --- 通訊 API 📞💬📧 ---------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| | Twilio API |存取簡訊、語音和訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://www.twilio.com/docs/usage/api)| |發送網格 API |存取電子郵件發送服務 |每天 100 封電子郵件 | API 金鑰 |[連結](https://docs.sendgrid.com/)| |郵件槍 API |存取電子郵件發送服務 |每月 5,000 封電子郵件 | API 金鑰 |[連結](https://documentation.mailgun.com/en/latest/)| | Nexmo API |存取簡訊、語音和訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://developer.nexmo.com/api)| |普利沃 API |存取簡訊、語音和訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://www.plivo.com/docs/)| |推送 API |即時通訊服務|免費套餐可用 | API 金鑰 |[連結](https://pusher.com/docs)| |郵戳API |存取電子郵件發送服務 |每月 100 封電子郵件 | API 金鑰 |[連結](https://postmarkapp.com/developer)| |訊號線 API |存取簡訊、語音和訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://signalwire.com/resources/docs)| |山魈API |存取電子郵件發送服務 |每月 2,000 封電子郵件 | API 金鑰 |[連結](https://mandrillapp.com/api/docs/)| |點擊發送 API |存取簡訊、語音和訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://developers.clicksend.com/docs/rest/v3/)| | Tropo API |存取簡訊、語音和訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://www.tropo.com/docs)| |鬆弛 API |存取 Slack 訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://api.slack.com/)| |不和諧 API |造訪 Discord 訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://discord.com/developers/docs/intro)| |縮放 API |存取 Zoom 視訊會議服務 |免費套餐可用 | API 金鑰 |[連結](https://marketplace.zoom.us/docs/api-reference/zoom-api)| |對講API |造訪 Intercom 訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://developers.intercom.com/intercom-api-reference)| --- 支付和金融 API 💳💸🏦 ------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |條紋 API |獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://stripe.com/docs/api)| |貝寶 API |獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://developer.paypal.com/docs/api/overview/)| |廣場 API |獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://developer.squareup.com/reference/square)| |布倫特里 API |獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://developer.paypal.com/braintree/docs/guides/overview)| | Authorize.net API | 授權.net API獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://developer.authorize.net/api/reference/index.html)| |格子 API |取得金融資料和服務|免費套餐可用 | API 金鑰 |[連結](https://plaid.com/docs/)| |德沃拉 API |獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://developers.dwolla.com/guides/)| |明智的API |獲得國際匯款服務 |免費套餐可用 | API 金鑰 |[連結](https://developer.transferwise.com/)| |世界支付 API |獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://developer.worldpay.com/docs)| | WePay API |獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://developer.wepay.com/)| |革命 API |取得金融資料和服務|免費套餐可用 | API 金鑰 |[連結](https://developer.revolut.com/docs)| | Xero API |取得會計和財務資料|免費套餐可用 | API 金鑰 |[連結](https://developer.xero.com/documentation/api)| | QuickBooks API |取得會計和財務資料|免費套餐可用 | API 金鑰 |[連結](https://developer.intuit.com/app/developer/qbo/docs/get-started)| |約德利 API |取得金融資料和服務|免費套餐可用 | API 金鑰 |[連結](https://developer.yodlee.com/apidocs)| |直覺 API |取得會計和財務資料|免費套餐可用 | API 金鑰 |[連結](https://developer.intuit.com/)| --- 分析與監控 API 📊📈📉 ------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |谷歌分析 API |存取 Google Analytics 資料 |免費套餐可用 | API 金鑰 |[連結](https://developers.google.com/analytics/devguides/reporting/core/v4)| |混合面板 API |存取 Mixpanel 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://developer.mixpanel.com/docs)| |振幅 API |存取 Amplitude 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://www.amplitude.com/developers/apis)| |熱罐 API |存取 Hotjar 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://developer.hotjar.com/docs)| |堆API |存取堆分析資料 |免費套餐可用 | API 金鑰 |[連結](https://docs.heap.io/docs)| | Piwik 專業版 API |存取 Piwik PRO 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://piwikpro.dev/documentation)| |段 API |存取細分分析資料 |免費套餐可用 | API 金鑰 |[連結](https://segment.com/docs/)| |瘋狂蛋API |存取 Crazy Egg 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://www.crazyegg.com/api)| |烏普拉 API |存取 Woopra 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://www.woopra.com/docs/api)| | Kissmetrics API |存取 Kissmetrics 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://www.kissmetrics.io/api)| |點擊 API |存取 Clicky 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://clicky.com/help/api)| |開放網路分析 API |存取開放網路分析資料 |免費套餐可用 | API 金鑰 |[連結](https://www.openwebanalytics.com/api/)| | Yandex Metrica API |存取 Yandex Metrica 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://yandex.com/support/metrica/quick-start.html)| |統計計數器 API |存取 StatCounter 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://statcounter.com/docs/)| | Chartbeat API |存取 Chartbeat 分析資料 |免費套餐可用 | API 金鑰 |[連結](https://chartbeat.com/docs/api/)| --- 自然語言處理 (NLP) API 🗣️🔍💬 --------------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |谷歌雲端自然語言處理 |自然語言處理服務| $300 免費贈金 | API 金鑰 |[連結](https://cloud.google.com/natural-language/docs)| | IBM 沃森 NLP |自然語言處理服務|免費套餐可用 | API 金鑰 |[連結](https://www.ibm.com/watson/services/natural-language-understanding/)| |微軟Azure NLP|自然語言處理服務| $200 免費贈金 | API 金鑰 |[連結](https://azure.microsoft.com/en-us/services/cognitive-services/text-analytics/)| |亞馬遜理解|自然語言處理服務|免費套餐可用 | API 金鑰 |[連結](https://aws.amazon.com/comprehend/)| |文字剃刀 |自然語言處理服務|每月 5000 個請求 | API 金鑰 |[連結](https://www.textrazor.com/docs)| |艾琳 NLP |自然語言處理服務|免費套餐可用 | API 金鑰 |[連結](https://aylien.com/text-api/)| |猴子學習 |文本分析與自然語言處理 |每月 300 次查詢 | API 金鑰 |[連結](https://monkeylearn.com/api/)| |意義雲 |文本分析與自然語言處理 |每月 20,000 個請求| API 金鑰 |[連結](https://www.meaningcloud.com/developer/apis)| | NLP 演算法 |自然語言處理演算法 |每月 10,000 次查詢 | API 金鑰 |[連結](https://algorithmia.com/developers)| |維特人工智慧 |自然語言處理與聊天機器人整合 |免費套餐可用 | API 金鑰 |[連結](https://wit.ai/docs)| |詞法解析 |文本分析與自然語言處理 |免費套餐可用 | API 金鑰 |[連結](https://www.lexalytics.com/developers)| | SapienAPI |自然語言處理服務|免費套餐可用 | API 金鑰 |[連結](https://www.sapien.com/api)| |聊天機器人 |自然語言處理與聊天機器人整合 |免費套餐可用 |無 |[連結](https://chatterbot.readthedocs.io/en/stable/)| |蒂薩尼API |文本分析與自然語言處理 |每月 30,000 個請求| API 金鑰 |[連結](https://tisane.ai/documentation)| | DeepAI 文字 API |自然語言處理服務|免費套餐可用 | API 金鑰 |[連結](https://deepai.org/machine-learning-model/text-tagging)| --- 實用程式和工具 API 🛠️🔧⚙️ ----------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| | IP資訊| IP 位址資訊與地理位置 |每月 50,000 個請求| API 金鑰 |[連結](https://ipinfo.io/developers)| |打開天氣地圖 |天氣預報資料,包括預報和當前天氣 | 60 次通話/分鐘 | API 金鑰 |[連結](https://openweathermap.org/api)| | Twilio API |存取簡訊、語音和訊息服務 |免費套餐可用 | API 金鑰 |[連結](https://www.twilio.com/docs/usage/api)| |發送網格 API |存取電子郵件發送服務 |每天 100 封電子郵件 | API 金鑰 |[連結](https://docs.sendgrid.com/)| | Clearbit API |商業智慧資料|每月 50,000 個請求| API 金鑰 |[連結](https://clearbit.com/docs)| | IPStack | IP 地理定位與資訊 |每月 10,000 個請求| API 金鑰 |[連結](https://ipstack.com/documentation)| |抽象API |各種實用 API,如 IP 地理定位、電子郵件驗證 |每月 500 個請求 | API 金鑰 |[連結](https://www.abstractapi.com/)| | API 介面 |網頁抓取與自動化 |每月 10,000 個請求| API 金鑰 |[連結](https://docs.apify.com/api/v2)| |刮刀 API |網頁抓取工具|每月 5000 個請求 | API 金鑰 |[連結](https://www.scraperapi.com/documentation/)| |郵差 API | API開發與測試工具|無限| API 金鑰 |[連結](https://www.postman.com/api-documentation/)| |哨兵 API |應用程式監控與錯誤追蹤 |每月 5000 場活動 | API 金鑰 |[連結](https://docs.sentry.io/api/)| |條紋 API |獲得支付處理服務 |免費套餐可用 | API 金鑰 |[連結](https://stripe.com/docs/api)| | PDF.co API | PDF 產生與資料擷取 |每月 1000 個請求 | API 金鑰 |[連結](https://apidocs.pdf.co/)| |比特利API | URL 縮短與連結管理 |每月 1000 個請求 | API 金鑰 |[連結](https://dev.bitly.com/docs/)| | OpenCage 地理編碼 |正向和反向地理編碼 |每天 2,500 通電話 | API 金鑰 |[連結](https://opencagedata.com/api)| --- 政府和開放資料 API 🏛️📜📊 ---------------- |名稱 |描述 |免費等級限制 |認證|文件 | |--------------------------------|---------------- ------------ -------------------------------------- |-------------------- --|--------------------|----- ----------------------------------- --------| |資料.gov API |美國政府公開資料|無限|無 |[連結](https://www.data.gov/developers/apis)| |英國政府 API |英國政府公開資料|無限|無 |[連結](https://www.gov.uk/guidance/using-the-api)| |歐盟開放資料入口網站API |歐盟開放資料|無限|無 |[連結](https://data.europa.eu/euodp/en/developers-corner)| |世界銀行 API |全球發展資料|無限|無 |[連結](https://datahelpdesk.worldbank.org/knowledgebase/topics/125589)| |聯合國資料API |聯合國開放資料|無限|無 |[連結](https://data.un.org/Host.aspx?Content=API)| |經合組織資料 API |經合組織的經濟和社會資料|無限|無 |[連結](https://data.oecd.org/api/)| |人口普查 API |美國人口普查局資料|無限| API 金鑰 |[連結](https://www.census.gov/data/developers/data-sets.html)| |開放資料軟體 |不同來源的各種開放資料|無限| API 金鑰 |[連結](https://www.opendatasoft.com/)| |紐約市 API |紐約市開放資料 |無限|無 |[連結](https://opendata.cityofnewyork.us/)| |美國地質調查局API |美國地質調查局資料|無限| API 金鑰 |[連結](https://www.usgs.gov/products/data-and-tools/apis)| |美國宇航局API |存取 NASA 資料和圖像 |無限| API 金鑰 |[連結](https://api.nasa.gov/)| |開放狀態 API |美國各州立法資料|無限| API 金鑰 |[連結](https://openstates.org/data/)| |美國政府 API |美國政府資訊與服務|無限|無 |[連結](https://www.usa.gov/developer)| | Data.gov.au API |澳洲政府公開資料|無限|無 |[連結](https://data.gov.au/)| | HealthData.gov API |美國健康相關開放資料|無限|無 |[連結](https://healthdata.gov/)| --- \*\*如果您發現此內容有幫助, 請[買杯咖啡](https://buymeacoffee.com/deyurii)🌟✨\*\* --- 原文出處:https://dev.to/falselight/300-free-apis-every-developer-needs-to-know-3j76

簡化程式碼:20 多個方便的 JavaScript 函數

JavaScript 是一種函數式程式語言,函數扮演著至關重要的角色。它們允許您封裝可重複使用程式碼並執行特定任務。以下是一些可以讓您的生活更輕鬆的功能的快速範例: ### 常規功能 ``` function sum(a, b) { return a + b; } ``` ### 函數表達式 ``` const sum = function (a, b) { return a + b; }; ``` ### 箭頭功能 ``` const sum = (a, b) => { return a + b; }; // OR const sum = (a, b) => a + b; ``` ### 發電機功能 ``` function* indexGenerator() { let index = 0; while (true) { yield index++; } } const g = indexGenerator(); console.log(g.next().value); // => 0 console.log(g.next().value); // => 1 ``` ### 建立一個從 1 到 n 的數字陣列 ``` const range = (n) => Array.from({ length: n }, (_, i) => i + 1); console.log(range(10)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ``` ### 使用步驟建立一個從 1 到 n 的數字陣列 ``` const range = (n, step = 1) => Array.from({ length: n }, (_, i) => i * step); console.log(range(10, 2)); // [1, 3, 5, 7, 9] ``` ### 建立一個陣列並用一個值填充它 ``` const fill = (len, value) => Array(len).fill(value); console.log(fill(3, 0)); // [0, 0, 0] ``` ### 打亂陣列 ``` const shuffleArray = (arr) => arr.sort(() => 0.5 - Math.random()); console.log(shuffleArray([1, 2, 3, 4])); // [3, 2, 1, 4] ``` ### 從陣列中刪除重複項 ``` const removeDuplicated = (arr) => [...new Set(arr)]; console.log(removeDuplicated([1, 2, 3, 3, 4, 4, 5, 5, 6])); // Result: [ 1, 2, 3, 4, 5, 6 ] const removeDuplicate = (arr) => Object.values(arr.reduce((a, b) => (a[b] ? a : { ...a, [b]: b }), {})); console.log(removeDuplicate([1, 2, 3, 3])); // Result: [ 1, 2, 3, ] ``` ### 產生隨機數 ``` const random = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; console.log(random(1, 10)); // Result: 1 ~ 10 ``` ### 找到最大的數字 ``` const findLargest = (arr) => arr.map((subArr) => Math.max(...subArr)); console.log( findLargest([ [4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1], ]) ); // [5, 27, 39, 1001] ``` ### 找出最小的數字 ``` const findSmallest = (arr) => arr.map((subArr) => Math.min(...subArr)); console.log( findSmallest([ [4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1], ]) ); // [1, 18, 32, 857] ``` ### 從陣列中選擇一個隨機元素 ``` const pick = (arr) => arr[Math.floor(Math.random() * arr.length)]; console.log(pick([1, 2, 3, 4])); // 2 ``` ### 將陣列轉換為物件 ``` const toObject = (arr) => ({ ...arr }); console.log(toObject(["a", "b"])); // { 0: 'a', 1: 'b' } ``` ### 找出兩個陣列的交集 ``` const intersection = (arr1, arr2) => { const set = new Set(arr1); return arr2.filter((x) => set.has(x)); }; console.log(intersection([1, 2, 3], [2, 3, 4])); // [2, 3] ``` ### 從陣列中刪除虛假值 ``` const compact = (arr) => arr.filter(Boolean); console.log(compact([0, 1, false, 2, "", 3, "a", "e" * 23, NaN, "s", 34])); // [1, 2, 3, 'a', 's', 34] ``` ### 反轉字串 ``` const reverseString = (str) => str.split("").reverse().join(""); console.log(reverseString("hello")); // olleh ``` ### 字串是回文嗎 ``` const isPalindrome = (str) => str === str.split("").reverse().join(""); console.log(isPalindrome("madam")); // true ``` ### 檢查物件是否為空 ``` const isEmpty = (obj) => Object.keys(obj).length === 0; console.log(isEmpty({})); // true ``` ### 找出一個月中的天數 ``` const getDaysInMonth = (date) => new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); console.log(getDaysInMonth(new Date())); // 31 ``` ### 產生隨機顏色 ``` const getRandomColor = () => `#${Math.floor(Math.random() * 16777215).toString(16)}`; console.log(getRandomColor()); // #f0f0f0 const randomHex = () => `#${Math.floor(Math.random() * 0xffffff) .toString(16) .padEnd(6, "0")}`; console.log(randomHex()); // #f0f0f0 ``` --- ##### 必須閱讀(如果還沒有) https://dev.to/devsmitra/how-to-create-the-app-using-jsx-without-react-k08 https://dev.to/devsmitra/reactjs-signal-for-state-mangement-21pf https://dev.to/devsmitra/simplify-javascripts-async-concepts-with-one-gif-3c6a --- ###### 更多內容請造訪[Dev.to](https://dev.to/devsmitra "拉胡爾·夏爾馬(DevsMitra)") 。 --- 原文出處:https://dev.to/devsmitra/20-handy-javascript-functions-to-simplify-your-code-javascript-tutorial-i0e

想請教一下前端新手工作內容

不好意思打擾各位前輩 我是剛剛入職的新手前端,我想詢問一下前端的工作內容 --- **第一天**上班主管就丟給我一個他們之前開發寫到一半的專案, 要我修客服聊天室連線的問題,demo給我看一下問題出在哪, 之後我把專案打開整個人都麻了,裡面一大堆的文件,我都不知道是做什麼的, 哪個檔案是哪個頁面我都不知道,最後通靈才知道應該是使用SignalR這個套件, 不過我也沒有使用過,只知道他是用來實現ws連線技術的, 最後是下班前兩三個小時,主管自己過來操作讓他可以使用,我在旁邊看的一楞一楞的。 --- **第二天**主管讓我做不同語系,用i18next套件,把網頁上的文字設定到裡面, 這個其實沒問題,有問題的是我不知道哪個頁面對應到哪個檔案,檔案底下的組件又在哪裡, 有時候明明是member資料夾底下的頁面,同一資料夾裡面也有components的資料夾, 但頁面上有時候不只使用到member資料夾底下的組件,還用到了上層資料夾的組件, 我真的不是很明白,所以中午我就問說有沒有開發的流程圖之類的東西, 他只笑著跟我說:[沒有],我最後就一個一個點開,找不到的只能先記事本記錄下來之後在一起問。 --- **第三天**還是再做第二天的事情,但下午主管又丟另一個專案給我,是要修改串API的問題, 說現在有資料但不是他想要的,讓我去跟後端說明他想要什麼資料, 之後就開文件讓我看API是怎麼串的,他好像是把axios封裝起來做了很多處理,講解一下之後, 讓我去翻其他文件是怎麼串的。 --- 想請教一下各位前輩面對前端的工作內容, 我是不是應該在學得更深一點再開始找工作

宣布 AnalogJS 1.0 🚀

經過數月的開發和測試,我們很高興地宣布 AnalogJS 1.0 版本發布! `1.0`版本包含許多功能,可協助開發人員使用 Angular 更快地交付網站和應用程式。 此版本標誌著 Analog 的第一個主要版本,為開發人員使用 Analog 進行建置提供了更穩定的起點。我們將繼續從開發人員那裡獲得回饋,幫助我們繼續改進和創新專案。 特點⭐️ ---- Analog 是建構在 Angular 之上的元框架,由下一代開源建置工具[Vite](https://vitejs.dev)和開源伺服器引擎框架[Nitro](https://nitro.unjs.io)提供支援。以下是它的一些功能,包括: - 對 Vite 生態系統的一流支援(Vitest、Playwright、Cypress 等) - [基於檔案系統的路由](https://analogjs.org/docs/features/routing/overview) - [支援 Markdown](https://analogjs.org/docs/features/routing/content)頁面和博客 - [支援 API/伺服器路由](https://analogjs.org/docs/features/api/overview) - 具有網站地圖和 RSS 提要支援的混合[SSR](https://analogjs.org/docs/features/server/server-side-rendering) / [SSG](https://analogjs.org/docs/features/server/static-site-generation) - 支援 Angular CLI/ [Nx 工作區](https://analogjs.org/docs/integrations/nx) - 與[tRPC](https://trpc.io)整合以實現類型安全的伺服器交互 - 伺服器和部署支援 - 和更多! 貢獻和社區🤓 ------ 如果沒有核心貢獻者和合作者團隊,AnalogJS 就不會有今天的成就。 [羅賓·戈茨](https://twitter.com/goetzrobin) [馬爾科·斯塔尼米羅維奇](https://twitter.com/markostdev) [路易斯·卡斯特羅](https://twitter.com/LuisHCCDev) [週陳](https://twitter.com/nartc1410) [約書亞·莫羅尼](https://twitter.com/joshuamorony) [安德烈斯·維拉紐瓦](https://twitter.com/villanuevand) 此外,也要感謝該專案的[80 多名貢獻者](https://github.com/analogjs/analog#contributors-),無論是透過程式碼、文件、測試,還是只是嘗試該專案。 該專案已經在[GitHub](https://github.com/analogjs/analog)上擁有超過 2000 顆星,在[Discord](https://chat.analogjs.org)上擁有超過 500 名成員,在[Twitter/X](https://twitter.com/analogjs)上擁有超過 1000 名追蹤者,並被納入第一批[GitHub 加速器隊列](https://accelerator.github.com/)。 {% youtube H4U6udLcM-Q %} 如果您想嘗試 Analog,請查看這篇有關使用 Analog 和 Angular[建立部落格](https://dev.to/analogjs/how-to-build-a-blog-with-analog-and-angular-4pk2)的部落格文章。如果您想參與該專案,請查看[GitHub 儲存庫](https://github.com/analogjs/analog)。 下一步是什麼 ------ 我們將繼續使用 Analog 和 Angular 盡可能無縫地建立全端網站和應用程式,並透過與[Astro](https://astro.build) 、 [Nx](https://nx.dev) 、 [Vitest](https://analogjs.org/docs/features/testing/vitest) 、 [Storybook](https://storybook.js.org)等整合來擴展 Angular 生態系統。 我們還在 Analog 中引入了一種新的單文件元件格式,用於編寫元件和指令。 以下是`hello.analog`檔案的範例: ``` <script lang="ts"> import { signal } from '@angular/core'; const count = signal(0); function increment() { count.update(total => ++total); } </script> <template> <h2>Hello Analog</h2> Count: {{ count() }} <button (click)="increment()"> Increment </button> </template> <style> h2 { color: red; } </style> ``` 最初是使用 Angular 的元件和指令的`.ng`檔案副檔名,現已發展成為模擬 SFC,其功能包括支援[自動導入](https://github.com/analogjs/analog/discussions/901)、內聯 Markdown 模板、頁面路由等。隨著 Analog 未來的發展,我們將繼續迭代這種方法,並探索在 Angular 應用程式中啟用這種格式的選項。 我們已經收到了非常積極的回饋,甚至還收到了支援這種格式的進一步開發,包括[用於模擬 SFC 的 IDEA 插件](https://plugins.jetbrains.com/plugin/23913-analog?noRedirect=true),該插件可在 WebStorm 的 EAP 版本中使用。感謝 JetBrains 團隊的[Jan-Niklas Wortmann](https://twitter.com/niklas_wortmann)和[Piotr Tomiak](https://twitter.com/PiotrekTomiak)對此外掛程式的初步開發。您也可以在[GitHub](https://github.com/analogjs/idea-plugin)上為該插件做出貢獻。 與 Analog 合作🤝 ------------ 我們正在尋找與模擬專案合作的公司,以支持該專案的開發。感謝[Snyder Technologies](https://snyder.tech/)作為 Analog 的早期採用者和推動者,[感謝 Nx](https://nx.dev)作為贊助商加入我們,[感謝 House of Angular](https://houseofangular.io)以及該專案的許多其他支持者。 了解有關我們[合作機會](https://analogjs.org/docs/sponsoring)的更多資訊或直接聯繫贊助商\[at\]analogjs.org。 加入社群🥇 ----- - 存取[GitHub 儲存庫](https://github.com/analogjs/analog)並為其加註星標 - 加入[不和諧](https://chat.analogjs.org) - 在[推特](https://twitter.com/analogjs)上關注我們 如果您喜歡這篇文章,請點擊 :heart: 這樣其他人就會看到它。在 Twitter/X 上關注[AnalogJS](https://twitter.com/analogjs)和 \[me\] (https://twitter.com/brandontroberts),並訂閱我的[YouTube 頻道](https://youtube.com/brandonrobertsdev?sub_confirmation=1)以獲取更多內容! --- 原文出處:https://dev.to/analogjs/announcing-analogjs-10-19an

JavaScript 框架 - 邁向 2024 年

我不是第一個這麼說的人,但我還是要說,2023 年對 JavaScript 框架來說是個不平凡的一年。我們一直在關注的新技術最終顯示出它們可以交付,而舊框架正在復興,如果您不注意,您可能會錯過一個相當重大的轉變。 我預計 2024 年將繼續出現更大的全面變化。這次不是新技術,而是精細化。既然基礎已經存在,那麼還有很多事情要做。 -------------------- ## 伺服器優先 如果讓我為過去幾年選擇一個主題,那就是這個。這一直是爭論的焦點,但不可否認。幾年前,每個人都在談論漸進式 Web 應用程式和離線應用程式。但那個對話框幾乎消失了。 相反,我們會受到 HTMX 的敏銳智慧的影響,解釋為什麼 JavaScript 只是一個錯誤。 Astro 毫無歉意地接管了內容網站的開發。甚至 React Core 團隊也接受了 React Server Components 的伺服器簡單性,Dan Abramov 的演講令人信服地表達了這一點,該演講探討瞭如果 React 始終是伺服器優先會怎樣。 https://www.youtube.com/watch?v=zMf_xeGPn6s 那麼我們的單頁應用程式親愛的在這麼短的時間內發生了什麼?它是否仍然存在,還是我們生活在多頁面應用程式和僅伺服器渲染 HTML 的時代? ------------------ ## 回顧 2023 年 去年,我寫了一篇非常類似的文章,探討了新的一年 JavaScript 框架的趨勢,我認為這是一個很好的起點。 https://dev.to/this-is-learning/javascript-frameworks-heading-into-2023-nln 該文章中確定的三大技術趨勢成為去年討論的重要組成部分。 ### 訊號無所不在 從 2022 年底開始,Preact 和 Qwik 緊跟著 SolidJS 和 Vue 的腳步,採用這些 Reactive 原語,這種勢頭只會持續到 2023 年。 二月份,Angular 團隊宣布採用。這一訊息震驚了社群媒體。不僅。這是 Angular 的存在發生非常顯著變化的幾個因素之一。有人甚至稱之為「角度復興」。這是過去幾年我們第一次看到 React 團隊加入這場爭論,因為真正被問到的問題是「訊號什麼時候出現在 React 中?」。 我在下面的文章中寫了這個問題的更長的答案(以及在評論中與丹·阿布拉莫夫的討論)。 https://dev.to/this-is-learning/react-vs-signals-10-years-later-3k71 但簡短的回答是,訊號(至少作為 API)並不是他們感興趣的東西,而他們備受期待的「忘記」編譯器將扮演類似的角色。 但訊號傳播並沒有就此結束。 Lit 是 Google 的 Web 元件框架,推出了[Lit 3,具有第一方訊號支援](https://lit.dev/blog/2023-10-10-lit-3.0/#preact-signals-integration)。 Rich Harris 公佈了 Svelte 的未來,[他們新的基於訊號的「Runes」](https://svelte.dev/blog/runes),將成為即將推出的 Svelte 5 中反應性的主要來源。 2023 年結束訊號是大多數前端 JavaScript 框架的主要部分。 ### 混合路由 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mdtlafe81eo4jchqx37w.png) 去年,基於伺服器的路由得到了加強並發揮了新的作用。從 2022 年底開始,到今年,我們看到人們已經習慣了這種範式轉變,例如 React Server Components 和 Astro 的 View Transition API 整合。 前提是初始頁面載入後的伺服器渲染不應阻止客戶端導航,且客戶端導航不應意味著我們需要發送所有 JavaScript 來渲染可以靜態伺服器渲染的頁面部分。 值得注意的是,並非所有解決方案都是等效的,而且這個領域仍在建設中。我們正在進入一個新的空間,它不完全是單頁應用程式,也不完全是傳統的多頁面網站。需要進行新的權衡和新的理解。我們還沒有完成對陷阱的探索。 ### 邊緣網路:最後的前沿 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bss8a8hwf3qbozvvq9a6.jpg) 邊緣功能似乎是那些明顯的勝利之一。將伺服器移至更靠近最終用戶的位置,可以大幅減少延遲。使用更輕的執行時間可以大幅減少冷啟動時間。我們終於可以提供我們一直夢想的網路體驗。以靜態的速度實現動態。 好吧,如果有什麼不同的話,2023 年是成長的陣痛和邊緣的一年。我們開始非常熱情。畢竟,Cloudflare 發布了邊緣資料庫,我們最喜歡的所有提供者都開始提供邊緣功能,而我們最喜歡的框架正在加入開箱即用的支援。提供者成立了一個 WinterCG 委員會來討論平台標準化問題。未來就在這裡。 我們最終認識到,即使在這些邊緣功能中,某些 Node API 也是必不可少的。您可以感謝或討厭 Next 和 Vercel 將“AsyncLocalStorage”推送到每個執行時,但我們需要它。 我們也意識到邊緣資料庫永遠無法滿足所有應用程式。即使使用串流媒體,伺服器瀑布也是真實且有影響力的。是的,即使使用 React Server 元件也是如此。 但這確實實現了我去年提出的目標,透過分散式部署進行整體創作。我們看到伺服器函數(`server$`、`use server`),甚至像 Worker Functions 這樣的變體在今年年初出現,表明我們可以分發我們部署 API 的方式,並被 Solid、Qwik 和 Next 採用。 到年底 [Next 14 發布了新的實驗性部分預渲染](https://nextjs.org/blog/next-14),它允許單一請求從邊緣提供靜態內容,同時代理到伺服器-less 靠近資料庫的函數全部被串流傳輸,以提供類似Edge 的體驗,而無需在那裡部署整個應用程式。看到一些獨創性提供了兩全其美的解決方案真是太棒了。 ---------------- ## 展望 2024 年 ### 訊號年 我知道我已經在一篇文章中充分討論了信號,但真正的回報還沒有發生。我們在 JavaScript 中使用細粒度的類似 Signal 的原語已有 15 年了,那麼為什麼現在呢? 這不僅僅是關於擁有它們,而是關於你如何使用它們。 Vue 多年來一直在隱藏這些原語,React 和 MobX 也是如此,但這幾乎沒有觸及事情的發展方向。那就是細粒度渲染。 SolidJS 所普及的內容,現在以 Vue Vapor 的形式進入 Vue,以及 Svelte 5 中的 Svelte。這些只是已經宣布的內容。 我希望其他採用訊號的人能夠更自然地將它們融入框架中,以便更好地從中受益。 這個領域的潛力令人興奮,致力於將 Signals 引入瀏覽器的 TC-39 提案的小組包括來自每個主要 JavaScript 框架的代表,而這個小組並不總是與標準密切相關。 ### 基礎設施主導的發展 既然伺服器端渲染框架已經打了一針強心劑,那麼下一個合乎邏輯的地方就是繼續考慮最大限度地利用這項新功能為我們提供的功能。標準的製定很慢,WinterCG 也需要一些時間,但這不會阻止這裡的發展。 為了實現差異化,我預期框架和基礎設施供應商都會面臨壓力,要求他們提供只能在特定平台上運作的獨特功能。雖然 2023 年各個提供者都在推動平等,以提供超出其基本靜態和功能託管的類似功能(例如鍵值存儲 Blob),但我只看到這裡提供獨特價值的競爭正在升溫。 框架在這方面的作用是保持一致的創作體驗和思考模型,同時找到利用呈現給我們的新能力的方法。這與 2000 年代末的瀏覽器戰爭沒有什麼不同,而且未來還會有很多事情發生。 ### 人工智慧 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sma4crnqjxbx89hhh7r3.jpg) 去年從框架的角度談論人工智慧還為時過早。明年也可能如此。但它就在眼前。程式碼遷移和生成工具都是很棒的想法,但它們遇到了我們多年來使用視覺化無程式碼或低程式碼編輯器所遇到的相同問題。人機界麵點仍然至關重要。畢竟,程式碼是有生命的東西。它會隨著時間的推移而增長和維持。 在過去的一年裡,與其他框架作者交談時,我們發現它吸引了我們周圍的人,但還沒有達到明確我們在其中的角色的程度。但這種情況正在改變。 是的,人工智慧正在回答一個永恆的問題:為什麼你的應用程式速度很慢。 對開發人員工具的影響是一回事。但我們也看到我們的框架中內建即時性的潛力越來越大。我也不僅僅指用於持久後端的 Websockets。元框架中的 API 已經從簡單的 JSON 發展到使用 SolidStart、Qwik 和 Next 中的「伺服器功能」完全流式跨網路 JavaScript 執行。不難想像生成技術即時建立使用者介面。 -------------------------- ## 結論 ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pf0pc8fhlor9xnou9r8b.jpg) 2024 年可能會繼續我們過去幾年看到的成熟趨勢。從 2020-22 年,我們看到了許多新的 JavaScript(和 WASM)框架(Qwik、Million.js、Astro、Next 13、Remix、Hydrogen、SvelteKit、SolidStart、Leptos、Dioxus、HTMX),但這還不是去年的案例。我們已經找到了方法,現在我們需要充分發揮它們的潛力。 我不確定我們是否已經成功地解決了複雜性,這對像 Astro 或 HTMX 這樣的簡化解決方案給予了大力支持。但我仍然充滿希望。 期望每個人都就「單頁應用程式」到底是什麼或何時應該使用擺在我們面前的各種選項達成一致可能有點太過分了,但這些解決方案每天都在變得更有能力實現他們設定的目標出去做。 我們所知道的網頁開發是否會改變已經不再是一個問題。即使方向還不完全明確,革命已經來臨。期望在那裡見到你。 --- 原文出處:https://dev.to/this-is-learning/javascript-frameworks-heading-into-2024-i3l

React 設計模式 Design Patterns

![](https://refine.ams3.cdn.digitaloceanspaces.com/blog-banners/retool-alternative.png) ## 介紹: React 開發人員可以透過使用設計模式來節省時間和精力,設計模式提供了一種使用經過測試且可信賴的解決方案來解決問題的快速方法。它們支援低耦合的內聚模組,從而幫助 React 開發人員建立可維護、可擴展且高效的應用程式。在本文中,我們將探索 React 設計模式並研究它們如何改進 React 應用程式的開發。 ## 容器和表示模式 容器和表示模式是一種旨在將反應程式碼中的表示邏輯與業務邏輯分離的模式,從而使其模組化、可測試並遵循關注點分離原則。 大多數情況下,在 React 應用程式中,我們需要從後端/儲存取得資料或計算邏輯並在 React 元件上表示該計算的結果。在這些情況下,容器和表示模式大放異彩,因為它可用於將元件分為兩類,即: * 容器元件,充當負責資料取得或計算的元件。 * 表示元件,其工作是將獲取的資料或計算值呈現在 UI(使用者介面)上。 容器和表示模式的範例如下所示: ``` import React, { useEffect } from 'react'; import CharacterList from './CharacterList'; const StarWarsCharactersContainer:React.FC = () => { const [characters, setCharacters] = useState<Character>([]) const [isLoading, setIsLoading] = useState<boolean>(false); const [error, setError] = useState<boolean>(false); const getCharacters = async () => { setIsLoading(true); try { const response = await fetch("https://akabab.github.io/starwars-api/api/all.json"); const data = await response.json(); setIsLoading(false); if (!data) return; setCharacters(data); } catch(err) { setError(true); } finally { setIsLoading(true); } }; useEffect(() => { getCharacters(); }, []); return <CharacterList loading={loading} error={error} characters={characters} />; }; export default StarWarsCharactersContainer; ``` ``` // the component is responsible for displaying the characters import React from 'react'; import { Character } from './types'; interface CharacterListProps { loading: boolean; error: boolean; users: Character[]; } const CharacterList: React.FC<CharacterListProps> = ({ loading, error, characters }) => { if (loading && !error) return <div>Loading...</div>; if (!loading && error) return <div>error occured.unable to load characters</div>; if (!characters) return null; return ( <ul> {characters.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> ); }; export default CharacterList; ``` ## 有 Hooks 的元件組合 Hooks 是 React 16.8 中首次推出的全新功能。從那時起,他們在開發 React 應用程式中發揮了至關重要的作用。掛鉤是基本函數,可授予功能元件存取狀態和生命週期方法(以前僅可用於類別元件)的功能。另一方面,掛鉤可以專門設計來滿足元件要求並具有其他用例。 我們現在可以隔離所有狀態邏輯(一種需要反應性狀態變數的邏輯),並使用自訂掛鉤在元件中組合或使用它。因此,程式碼更加模組化和可測試,因為鉤子鬆散地綁定到元件,因此可以單獨測試。 帶有鉤子的元件組合示例如下所示: ``` // creating a custom hook that fetches star wars characters export const useFetchStarWarsCharacters = () => { const [characters, setCharacters] = useState<Character>([]) const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(false); const controller = new AbortController() const getCharacters = async () => { setIsLoading(true); try { const response = await fetch( "https://akabab.github.io/starwars-api/api/all.json", { method: "GET", credentials: "include", mode: "cors", headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, signal: controller.signal } ); const data = await response.json(); setIsLoading(false); if (!data) return; setCharacters(data); } catch(err) { setError(true); } finally { setIsLoading(true); } }; useEffect(() => { getCharacters(); return () => { controller.abort(); } }, []); return [ characters, isLoading, error ]; }; ``` 建立自訂鉤子後,我們將其導入到我們的 **StarWarsCharactersContainer** 元件中並使用它; ``` // importing the custom hook to a component and fetch the characters import React from 'react'; import { Character } from './types'; import { useFetchStarWarsCharacters } from './useFetchStarWarsCharacters'; const StarWarsCharactersContainer:React.FC = () => { const [ characters, isLoading, error ] = useFetchStarWarsCharacters(); return <CharacterList loading={loading} error={error} characters={characters} />; }; export default StarWarsCharactersContainer; ``` --- <橫幅隨機/> --- ## 使用Reducers進行狀態管理 大多數情況下,處理元件中的許多狀態會導致許多未分組狀態的問題,這可能是處理起來很麻煩且具有挑戰性的。在這種情況下,減速器模式可能是有用的選擇。我們可以使用減速器將狀態分類為某些操作,這些操作在執行時可以變更分組的狀態。 此模式允許使用它的開發人員控制元件和/或掛鉤的狀態管理,讓他們在發送事件時管理狀態變更。 使用減速器模式的範例如下所示: ![圖片描述](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mbob3gmfxws8k4ti0cyx.png) 在上面的程式碼中,元件調度兩個操作: * “**login**”操作類型會觸發狀態更改,影響三個狀態值,即 **loggedIn**、**user**、**token**。 *“**註銷**”操作只是將狀態重設為其初始值。 ## 提供者的資料管理 提供者模式對於資料管理非常有用,因為它利用上下文 API 透過應用程式的元件樹傳遞資料。這種模式是一種有效的解決支柱鑽井問題的方法,這一直是 React 開發中普遍關注的問題。 為了實現提供者模式,我們首先建立一個提供者元件。 Provider 是 Context 物件提供給我們的一個高階元件。我們可以利用React提供的createContext方法來建構一個Context物件。 ``` export const ThemeContext = React.createContext(null); export function ThemeProvider({ children }) { const [theme, setTheme] = React.useState("light"); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); } ``` 建立提供者後,我們將使用建立的提供者元件封裝依賴上下文 API 中的資料的元件。 為了從上下文 API 取得資料,我們呼叫 useContext 鉤子,它接受上下文作為參數(在本例中為 **ThemeContext**)。 ``` import { useContext } from 'react'; import { ThemeProvider, ThemeContext } from "../context"; const HeaderSection = () => { <ThemeProvider> <TopNav /> </ThemeProvider>; }; const TopNav = () => { const { theme, setTheme } = useContext(ThemeContext); return ( <div style={{ backgroundColor: theme === "light" ? "#fff" : "#000 " }}> ... </div> ); }; ``` ## 使用 HOC(高階元件)增強元件 高階元件接受一個元件作為參數,並傳回一個注入了附加資料或功能的增壓元件。 React 中 HOC 的可能性是由於 React 更喜歡組合而不是繼承。 高階元件 (HOC) 模式提供了一種增加或修改元件功能的機制,促進元件重複使用和程式碼共用。 HOC 模式的範例如下所示: ``` import React from 'react' const higherOrderComponent = Component => { return class HOC extends React.Component { state = { name: 'John Doe' } render() { return <Component name={this.state.name {...this.props} /> } } const AvatarComponent = (props) => { return ( <div class="flex items-center justify-between"> <div class="rounded-full bg-red p-4"> {props.name} </div> <div> <p>I am a {props.description}.</p> </div> </div> ) } const SampleHOC = higherOrderComponent(AvatarComponent); const App = () => { return ( <div> <SampleHOC description="Frontend Engineer" /> </div> ) } export default App; ``` 在上面的程式碼中, **<AvatarComponent/>** 由 **higherOrderComponent** 提供 props,它將在內部使用。 ## 複合元件 複合元件模式是一種 React 設計模式,用於管理由子元件組成的父元件。 這種模式背後的原理是將父元件分解為更小的元件,然後使用 props、上下文或其他反應資料管理技術來管理這些較小元件之間的互動。 當需要建立由較小元件組成的可重複使用、多功能元件時,這種模式會派上用場。它使開發人員能夠建立複雜的 UI 元件,這些元件可以輕鬆自訂和擴展,同時保持清晰簡單的程式碼結構。 複合元件模式的用例範例如下所示: ``` import React, { createContext, useState } from 'react'; const ToggleContext = createContext(); function Toggle({ children }) { const [on, setOn] = useState(false); const toggle = () => setOn(!on); return ( <ToggleContext.Provider value={{ on, toggle }}> {children} </ToggleContext.Provider> ); } Toggle.On = function ToggleOn({ children }) { const { on } = useContext(ToggleContext); return on ? children : null; } Toggle.Off = function ToggleOff({ children }) { const { on } = useContext(ToggleContext); return on ? null : children; } Toggle.Button = function ToggleButton(props) { const { on, toggle } = useContext(ToggleContext); return <button onClick={toggle} {...props} />; } function App() { return ( <Toggle> <Toggle.On>The button is on</Toggle.On> <Toggle.Off>The button is off</Toggle.Off> <Toggle.Button>Toggle</Toggle.Button> </Toggle> ); } ``` ## 道具組合 這需要從幾個相關的 props 建立一個物件,並將其作為單個 props 傳遞給元件。 這種模式允許我們清理程式碼並使管理 props 變得更簡單,當我們想要將大量相關屬性傳遞給元件時,它特別有用。 ``` import React from 'react'; function P(props) { const { color, size, children, ...rest } = props; return ( <p style={{ color, fontSize: size }} {...rest}> { children } </p> ); } function App() { const paragraphProps = { color: "red", size: "20px", lineHeight: "22px" }; return <P {...paragraphProps}>This is a P</P>; } ``` ## 受控輸入 受控輸入模式可用於處理輸入欄位。此模式涉及使用事件處理程序在輸入欄位的值發生變更時更新元件狀態,以及將輸入欄位的目前值儲存在元件狀態中。 由於React 控制元件的狀態和行為,因此該模式使程式碼比不受控制的輸入模式更具可預測性和可讀性,後者不使用元件的狀態,而是直接透過DOM(文件物件模型)對其進行控制。 受控輸入模式的用例範例如下所示: ``` import React, { useState } from 'react'; function ControlledInput() { const [inputValue, setInputValue] = useState(''); const handleChange = (event) => { setInputValue(event.target.value); }; return ( <input type="text" value={inputValue} onChange={handleChange} /> ); } ``` ## 使用forwardRefs 管理自訂元件 稱為 ForwardRef 的高階元件將另一個元件作為輸入並輸出一個傳遞原始元件引用的新元件。透過這樣做,子元件的 ref(可用於檢索底層 DOM 節點或元件實例)可供父元件存取。 當建立與第三方程式庫或應用程式中的另一個自訂元件互動的自訂元件時,在工作流程中包含 ForwardRef 模式非常有幫助。透過授予對庫的 DOM 節點或另一個元件的 DOM 實例的存取權限,它有助於將此類元件的控制權轉移給您。 forwardRef 模式的用例範例如下所示: ``` import React from "react"; const CustomInput = React.forwardRef((props, ref) => ( <input type="text" {...props} ref={ref} /> )); const ParentComponent = () => { const inputRef = useRef(null); useEffect(() => { inputRef.current.focus(); }, []); return <CustomInput ref={inputRef} />; }; ``` 在上面的程式碼中,我們使用「forwardRefs」從元件「<ParentComponent/>」觸發了另一個元件「<CustomInput/>」的焦點。 # 結論 我們在本文中討論了 React 設計模式,包括高階元件、容器呈現元件模式、複合元件、受控元件等等。透過將這些設計模式和最佳實踐合併到您的 React 專案中,您可以提高程式碼質量,促進團隊協作,並使您的應用程式更具可擴展性、靈活性和可維護性。 --- 原文出處:https://dev.to/refine/react-design-patterns-230o

用Github Page整理作品集

因為一直找不到工作(...汗)所以來整理作品 [成果展示](https://superyngo.github.io/to_do_list/) 基本上是參考[Let's Write](https://www.letswrite.tw/)做的[Demo](https://letswritetw.github.io/letswrite-food-check/) 在頁面下方有作品導覽以及Github連結 使用工具: 1.Github Page 2.[Google Tag Manager](https://tagmanager.google.com/#/home) 步驟: 1.申請GTM並取得GTM代碼 2.將GTM代碼插入所有專案的index.html中,並將所有專案上傳github,開啟page頁面 3.另外做一個myNavbat的github page,將所有專案連結放進去,可參考[我做的](https://github.com/superyngo/myNavbar) 4.用GTM的「自訂HTML」功能將myNavbar和github連結塞進所有專案中,參考代碼如下: ``` <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" /> <div class="myNav"></div> <div class="github"> <a class="githubHerf"> <i class="fa fa-github" aria-hidden="true"></i> </a> </div> <script> var githubHerf=document.querySelector(".githubHerf") githubHerf.setAttribute("href","https://github.com/superyngo"+{{Page Path}}) var myNav2 = document.querySelector(".myNav"); var iframe2 = document.createElement("iframe"); iframe2.setAttribute("src", "https://superyngo.github.io/myNavbar/"); iframe2.setAttribute("width", "100%"); iframe2.setAttribute("frameborder", "0"); myNav2.appendChild(iframe2) </script> <style> body{ background-color: #fff0df; } .github { position: fixed; left: 0; bottom: 0; display: flex; width: 100px; height: 100px; cursor: pointer; z-index: 2; :hover { position: absolute; left: 10px; bottom: 5px; font-size: 3rem; color: #fff; scale: 0.9; } } .github::before { content: ""; width: 0; height: 0; border-style: solid; border-width: 100px 0 0 100px; border-color: transparent transparent transparent #6e5494; } .github .fa { position: absolute; left: 10px; bottom: 5px; font-size: 3rem; color: #fff; } @media screen and (max-width: 600px) { :root { font-size: 12px; } .github { width: 70px; height: 70px; } .github::before { border-width: 70px 0 0 70px; } .github .fa { left: 8px; bottom: 4px; font-size: 2rem; } } </style> ``` 注意事項; 1.不知為何我GTM塞iframe一直不給過,所以用append的。 2.iframe內的超連結預設會在iframe內開啟,要避免只要在myNavbar的head裡加上<base target="_parent" />就可以了。 3當初做這些作業時完全沒考慮theme和RWD,花了一些時間但又不想花太多時間結果就勉勉強強用手機也都能開。 閒聊: 前陣子都在codeSignal上刷題,看別人解法真的很神,學很多... 有沒有北部公司缺人啊...投履歷都沒人回..中年轉行真的不行嗎...

Ruby on Rails 之父:我怎麼學會寫程式的?

DHH,本名David Heinemeier Hansson,Basecamp合夥人、Google 2005年度駭客、業餘賽車手,他最知名的身份是網路開發框架Ruby on Rails的發明者。 DHH曾在部落格發表他學寫程式的心得: https://signalvnoise.com/posts/2582-how-do-i-learn-to-program 看過之後覺得獲益良多,特此翻譯出來和大家分享。 --- ## 我怎麼學會寫程式的? 我花了二十幾年才真的學會怎麼寫程式。不是因為我嘗試的不夠,而是因為我一直用錯誤的方法。我以前都看著那些教材、範本照做,寫出一些我根本沒興趣繼續往下寫的東西。這是為了學習而學習。 我知道這方法對有些人管用,這些人就是很樂意學習新東西。我真羨慕你們。但這對我不管用,而且我知道很多人也沒辦法用這種方式學習。 為了解決鳥事而寫程式———對我來說這才管用。寫程式是因為非這麼做不可。寫程式是因為我他媽的在乎自己所寫的東西,而且我希望它越快完成越好。 這就是我學寫Ruby的方法。我把目標定為,用Ruby把Basecamp寫出來。當你因為一個目標而去學習,每件事的先後順序就變得非常清楚。我到底該做什麼才能讓這幾個訊息順利在Ruby執行?哦,我需要在這裡加一個迴圈。哦,我需要在哪裡抓些資料庫的資料出來。 決定目標的當下,你的點子就完成一半了、而且你還知道了該怎麼做。 簡單來說,就是從一些確實的東西開始做起,接著讓時鐘發出「滴」聲,然後讓它發出「答」聲。

現代前端框架的背後觀念:新手必讀基本功

框架背後有什麼必學觀念的?這篇文章簡單整理如下 原文出處:https://dev.to/lexlohr/concepts-behind-modern-frameworks-4m1g --- 很多初學者會問“我應該學哪個框架?”和“學一個框架之前需要學多少JS或TS?” - 無數自以為是的文章都在宣傳作者首選框架或庫的優勢,而不是向讀者展示其背後的概念、教他們如何做出明智的決定。讓我們先解決第二個問題: ## “在學習框架之前要學多少 JS/TS?” 盡可能多地理解它們的基本概念。您將需要了解基本資料類型、函數、基本運算符和文檔對像模型 (DOM),這是 HTML 和 CSS 在 JS 中的基礎。雖然先學一點當然沒關係,但沒必要先精通框架或庫。 如果您是一個完全的初學者,[JS for cats](http://jsforcats.com/) 可能是您第一步的好資源。繼續前進,直到您感到自信為止,然後繼續前進,直到您開始感到自信不足。那就是你了解足夠的 JS/TS 並可以開始學框架的時間。其餘的你可以邊走邊學。 ## “你指的是什麼概念?” - 狀態 - 效果 - 記憶化 - 模板和渲染 所有現代框架都從這些概念中衍伸出它們的功能。 ### 狀態 狀態只是讓您的應用程式跑起來的資料。它可能在全局級別上,適用於應用程式的較大部分,或適用於單個元件。讓我們以一個簡單的計數器為例。它保留的計數是狀態。我們可以讀取狀態並寫入狀態以增加計數。 最簡單的表示通常是一個變數,其中包含我們的狀態所包含的資料: ``` let count = 0; const increment = () => { count++; }; const button = document.createElement('button'); button.textContent = count; button.addEventListener('click', increment); document.body.appendChild(button); ``` 但是這段程式碼有一個問題:對 count 的更改,就像對 increment 所做的更改一樣,不會更新按鈕的文本內容。我們可以手動更新所有內容,但這對於更複雜的用例來說並不能很好地擴展。 `count` 更新其用戶的能力稱為*反應性*。這是通過訂閱並重新執行應用程式的訂閱部分來更新的。 幾乎每個現代前端框架和庫都有一種響應式管理狀態的方法。解決方案分為三部分,至少採用其中之一或混合使用: - Observables / Signals - Reconciliation of immutable updates - Transpilation #### Observables / Signals Observables 基本上是允許藉由訂閱閱讀器的函數來進行讀取的結構。然後訂閱者在更新時重新執行: ``` const state = (initialValue) => ({ _value: initialValue, get: function() { /* subscribe */; return this._value; }, set: function(value) { this._value = value; /* re-run subscribers */; } }); ``` 這個概念的第一個用途之一是在 [knockout](https://knockoutjs.com/) 中,它使用相同的函數,帶和不帶參數進行寫/讀存取。 這種模式目前正在以「信號」的形式復興,例如在 [Solid.js](https://www.solidjs.com/docs/latest/api#createsignal) 和 [preact signals](https://preactjs.com /guide/v10/signals/),但在 [Vue](https://vuejs.org/) 和 [Svelte](https://svelte.dev/) 的底層使用了相同的模式。 [RxJS](https://rxjs.dev/) 為 [Angular](https://angular.io/) 的反應層提供動力,是這一原則的延伸,超越了簡單狀態,但有人可能會爭辯說它模擬複雜性的能力可能反而綁手綁腳。 [Solid.js](https://www.solidjs.com/) 還以儲存(可以通過 setter 操作的物件)和可變(可以像平常一樣使用的物件)的形式進一步抽象這些信號 JS 物件或 [Vue](https://vuejs.org/) 中的狀態來處理巢狀狀態物件。 #### Reconciliation of immutable states 不變性意味著如果一個物件的屬性發生變化,整個物件引用必須改變,所以簡單的引用比較可以很容易地檢測到是否有變化,這就是協調器所做的。 ``` const state1 = { todos: [{ text: 'understand immutability', complete: false }], currentText: '' }; // updating the current text: const state2 = { todos: state1.todos, currentText: 'understand reconciliation' }; // adding a to-do: const state3 = { todos: [ state.todos[0], { text: 'understand reconciliation', complete: true } ], currentText: '' }; // this breaks immutability: state3.currentText = 'I am not immutable!'; ``` 如您所見,未更改專案的引用被重新使用。如果協調器檢測到不同的物件引用,它會再次使用狀態(props, memos, effects, context)來重跑所有元件。由於讀取存取是被動的,這需要手動指定對反應值的依賴性。 顯然,您不是以這種方式定義狀態。您可以從現有屬性建置它,也可以使用所謂的 reducer。reducer 是一個函數,它接受一個狀態並返回另一個狀態。 [react](https://reactjs.org/) 和 [preact](https://preactjs.com/) 使用此模式。它適合與 vDOM 一起使用,我們將在稍後描述模板時探討它。 並非每個框架都使用其 vDOM 來使狀態完全響應。 例如 [Mithril.JS](https://mithril.js.org/components.html#state),元件會在設置的事件後變化後更新狀態;否則你必須手動觸發 `m.redraw()`。 #### Transpilation Transpilation 是一個建置步驟,它重寫我們的程式碼以使其在舊瀏覽器上執行或賦予它額外的能力;在這種情況下,該技術用於將簡單變數更改為反應系統的一部分。 [Svelte](https://svelte.dev/) 基於一個轉譯器,該轉譯器還通過看似簡單的變數宣告和存取為其反應式系統提供動力。 順便說一句,[Solid.js](https://solidjs.com) 使用轉譯,但不是針對它的狀態,只是針對模板。 ### 效果 在大多數情況下,我們需要對反應狀態做更多的事情,而不是從中衍伸並渲染到 DOM 中。我們必須管理副作用,這些都是由於視圖更新之外的狀態更改而發生的所有事情(儘管 [Solid.js](https://solidjs.com) 等一些框架也將視圖更改視為效果)。 還記得第一個例子中,訂閱處理被故意遺漏的狀態嗎?讓我們完成這個處理效果,來作為對更新的反應: ``` const context = []; const state = (initialValue) => ({ _subscribers: new Set(), _value: initialValue, get: function() { const current = context.at(-1); if (current) { this._subscribers.add(current); } return this._value; }, set: function(value) { if (this._value === value) { return; } this._value = value; this._subscribers.forEach(sub => sub()); } }); const effect = (fn) => { const execute = () => { context.push(execute); try { fn(); } finally { context.pop(); } }; execute(); }; ``` 這基本上是 [preact signals](https://preactjs.com/guide/v10/signals/) 或 [Solid.js](https://solidjs.com) 中反應狀態的簡化,沒有錯誤處理和狀態突變模式(使用接收前一個值並返回下一個值的函數),但這很容易加入。 它允許我們使前面的範例具有反應性: ``` const count = state(0); const increment = () => count.set(count.get() + 1); const button = document.createElement('button'); effect(() => { button.textContent = count.get(); }); button.addEventListener('click', increment); document.body.appendChild(button); ``` > ☝ 使用您的開發人員工具在 [空白頁面](about:blank) 中嘗試上述兩個程式碼塊。 在大多數情況下,框架允許不同的時間安排,讓效果在渲染 DOM 之前、期間或之後執行。 ### 記憶化 Memoization 意味著緩存從狀態計算的值,它會從狀態衍伸的變化更新時更新。它基本上是一種回傳衍伸狀態的效果。 在重新執行元件功能的框架中,例如 [react](https://reactjs.org/) 和 [preact](https://preactjs.com/),這讓某些複雜計算不需要每次都重複計算。 對於其他框架,情況恰恰相反:它允許您選擇部分組件進行響應式更新,同時緩存之前的計算。 對於我們簡單的反應式系統,memo 看起來像這樣: ``` const memo = (fn) => { let memoized; effect(() => { if (memoized) { memoized.set(fn()); } else { memoized = state(fn()); } }); return memoized.get; }; ``` ### 模板化和渲染 現在我們有了純的、衍伸的和緩存形式的狀態,我們想把它展示給用戶。在我們的範例中,我們直接使用 DOM 來加入按鈕並更新其文本內容。 為了對開發人員更加友好,幾乎所有現代框架都支持一些特定領域的語言來編寫類似於程式碼中所需輸出的內容。儘管有不同的風格,比如 `.jsx`、`.vue` 或 `.svelte` 文件,但它們都歸結為用類似於 HTML 的程式碼表示 DOM,因此基本上 ``` <div>Hello, World</div> // in your JS // becomes in your HTML: <div>Hello, World</div> ``` 你可能會問“我要把狀態放在哪裡?”。很好的問題。在大多數情況下,`{}` 用於表示屬性和節點周圍的動態內容。 最常用的 JS 模板語言擴展無疑是 JSX。對於 [react](https://reactjs.org),它被編譯為純 JavaScript,其方式允許它建立 DOM 的虛擬表示,一種稱為虛擬文檔對像模型或簡稱 vDOM 的內部視圖狀態。 這樣設計的原因是:建立物件比存取 DOM 快得多,所以如果你能用當前的替換後者,你可以節省時間。但是,如果您在任何情況下都有大量 DOM 更改或建立無數物件而沒有更改,則此解決方案的優點就變成必須通過「記憶化」來規避的缺點。 ``` // original code <div>Hello, {name}</div> // transpiled to js createElement("div", null, "Hello, ", name); // executed js { "$$typeof": Symbol(react.element), "type": "div", "key": null, "ref": null, "props": { "children": "Hello, World" }, "_owner": null } // rendered vdom /* HTMLDivElement */<div>Hello, World</div> ``` 不過,JSX 不僅限於 react。例如,Solid 使用其轉譯器更徹底地更改程式碼: ``` // 1. original code <div>Hello, {name()}</div> // 2. transpiled to js const _tmpl$ = /*#__PURE__*/_$template(`<div>Hello, </div>`, 2); (() => { const _el$ = _tmpl$.cloneNode(true), _el$2 = _el$.firstChild; _$insert(_el$, name, null); return _el$; })(); // 3. executed js code /* HTMLDivElement */<div>Hello, World</div> ``` 雖然轉譯後的程式碼乍看可能令人望而生畏,但解釋這裡發生的事情卻相當簡單。首先,建立包含所有靜態部分的模板,然後複製它以建立其內容的新實體,並加入動態部分並連接以根據狀態更改進行更新。 Svelte 走得更遠,不僅可以轉換模板,還可以轉換狀態。 ``` // 1. original code <script> let name = 'World'; setTimeout(() => { name = 'you'; }, 1000); </script> <div>Hello, {name}</div> // 2. transpiled to js /* generated by Svelte v3.55.0 */ import { SvelteComponent, append, detach, element, init, insert, noop, safe_not_equal, set_data, text } from "svelte/internal"; function create_fragment(ctx) { let div; let t0; let t1; return { c() { div = element("div"); t0 = text("Hello, "); t1 = text(/*name*/ ctx[0]); }, m(target, anchor) { insert(target, div, anchor); append(div, t0); append(div, t1); }, p(ctx, [dirty]) { if (dirty & /*name*/ 1) set_data(t1, /*name*/ ctx[0]); }, i: noop, o: noop, d(detaching) { if (detaching) detach(div); } }; } function instance($$self, $$props, $$invalidate) { let name = 'World'; setTimeout( () => { $$invalidate(0, name = 'you'); }, 1000 ); return [name]; } class Component extends SvelteComponent { constructor(options) { super(); init(this, options, instance, create_fragment, safe_not_equal, {}); } } export default Component; // 3. executed JS code /* HTMLDivElement */<div>Hello, World</div> ``` 也有例外。例如,在 [Mithril.js](https://mithril.js.org/) 中,雖然可以使用 JSX,但我們鼓勵您編寫 JS: ``` // 1. original JS code const Hello = { name: 'World', oninit: () => setTimeout(() => { Hello.name = 'you'; m.redraw(); }, 1000), view: () => m('div', 'Hello, ' + Hello.name + '!') }; // 2. executed JS code /* HTMLDivElement */<div>Hello, World</div> ``` 雖然大多數人會發現開發人員缺乏經驗,但其他人更喜歡完全控制他們的程式碼。根據他們主要想解決的問題,缺少轉譯步驟甚至可能是有益的。 儘管很少有人這樣推薦,許多其他框架都允許在不進行轉譯的情況下使用。 ## “我現在應該學習什麼框架或庫?” 我有一些好訊息和一些壞訊息要告訴你。 壞訊息是:沒有萬靈丹。沒有哪個框架在每個方面都比其他框架好得多。他們每個人都有自己的優勢和妥協。 [React](https://reactjs.org/) 有它的鉤子規則,[Angular](https://angular.io/) 缺乏簡單的信號,[Vue](https://vuejs.org/)缺乏向後兼容性,[Svelte](https://svelte.dev/) 不能很好地擴展,[Solid.js](https://www.solidjs.com/) 禁止解構,[Mithril.js]( https://mithril.js.org/) 並不是真正的反應式,僅舉幾例。 好訊息是:沒有錯誤的選擇——至少,除非專案的要求真的很有限,無論是在 bundle 大小還是性能方面。每個框架都會完成它的工作。有些人可能需要配合團隊的設計決策,這可能會使您的速度變慢,但無論如何您都應該能夠獲得可行的結果。 話雖這麼說,沒有框架也可能是一個可行的選擇。許多專案都被過度使用 JavaScript 破壞了。其實帶有一些互動性的靜態頁面就可以完成這項工作。 現在您已經了解了這些框架和庫應用的概念,請選擇最適合您當前任務的概念。不要害怕在下一個專案中切換框架。沒有必要學習所有這些。 如果你嘗試一個新的框架,我發現最有幫助的事情之一就是跟它的社群有所連結,無論是在社群媒體、discord、github 還是其他地方。他們可以告訴您哪些方法適合他們的框架,這將幫助您更快地獲得更好的解決方案。 ## “拜託,你*總是*有個人喜好吧!” 如果你的主要目標是就業,我建議學習 [react](https://reactjs.org/)。如果您想要輕鬆的性能和控制體驗,請嘗試 [Solid.js](https://solidjs.com);你可能會在 Solid 的 [Discord](https://discord.com/invite/solidjs) 上見到我。 但請記住,所有其他選擇都同樣有效。你不應該因為我這麼說就選擇一個框架,而應該使用最適合你的框架。

如何在 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 中渲染列表,乍看之下,只是個簡單的面試問題。但其實可深可淺。下次面試時遇到這問題,可以思考一下此篇文章談到的各個面向。