在JavaScript中处理表單

發現在HTML和JavaScript中處理表單的基礎知識 表單是HTML和網頁平台的一個非常重要的組成部分。它們允許用戶與頁面互動,並可以… 搜索網站上的內容 觸發過濾器以縮小結果頁面 發送信息 等等。 默認情況下,表單將其內容提交到服務器端點,默認情況下是頁面URL本身: <form> ... <input type="submit"> </form> 我們可以通過設置表單元素的 action 屬性來覆蓋此行為,使用由 method 屬性定義的HTML方法,默認為 GET: <form action="/contact" method="POST"> ... <input type="submit"> </form> 點擊提交輸入元素後,瀏覽器會向同一域(協議、域名和端口)的 /contact URL 發送一個POST請求。 使用JavaScript,我們可以攔截此事件,異步提交表單(使用XHR和Fetch),還可以對單個表單元素上的事件做出反應。 攔截表單提交事件 我剛剛描述了表單的默認行為,未使用JavaScript。 要開始使用JavaScript與表單一起工作,您需要在表單元素上攔截 submit 事件: const form = document.querySelector('form') form.addEventListener('submit', event => { // 檢測到提交事件 }) 現在,在提交事件處理程序函數內部,我們調用 event.preventDefault() 方法來阻止默認行為,避免表單提交重新加載頁面: const form = document.querySelector('form') form.addEventListener('submit', event => { // 檢測到提交事件 event.preventDefault() }) 此時,單擊表單中的提交事件按鈕將不會做任何事情,除了讓我們控制。 處理輸入元素事件 我們可以在表單元素上監聽許多事件 input:當元素值更改時,在表單元素上觸發 change:當元素值更改時,在表單元素上觸發。對於文本 input 元素和 textarea,它僅在元素失去焦點時觸發一次(每輸入個字元不觸發一次) cut:當用戶從表單元素中剪切文本時觸發 copy:當用戶從表單元素中複製文本時觸發 paste:當用戶將文本粘貼到表單元素中時觸發 focus:當表單元素獲得焦點時觸發 blur:當表單元素失去焦點時觸發 這裡有一個Codepen上的示例表單演示:...

在JavaScript中生成隨機而唯一的字符串

在構建我的在線課程平台時,我遇到了生成數千個唯一URL的問題。 每個參與課程的人都會被分配一個唯一的URL。後端知道所有這些URL並將有效的URL映射到課程內容上。 我希望有一個唯一的URL,因為我可以將URL關聯到購買郵件。 這樣,我就可以避免使用登錄功能,同時讓每個人都有一個單獨的URL,以便在URL意外或故意被公開分享時,我可以阻止濫用。 於是我開始寫我的Node.js腳本。 我使用了randomstring這個包,並將數字添加到Set對象中,直到我得到想要的數量。使用Set意味著每個字符串都是唯一的,因為調用add並傳遞重複的字符串不會產生任何效果。 我創建了一個名為generateStrings()的函數來返回這個Set: const generateStrings = (numberOfStrings, stringLength) => { const randomstring = require('randomstring') const s = new Set() while (s.size < numberOfStrings) { s.add(randomstring.generate(stringLength)) } return s } 可以這樣調用它: const strings = generateStrings(100, 20) 其中100是我想要的字符串數量,20是每個字符串的長度。 一旦我們獲得了這個Set,我們可以使用values()Set方法來遍歷它們: for (const value of strings.values()) { console.log(value) }

在JavaScript中動態選擇對象的方法

學習如何在JavaScript中動態訪問對象的方法 有時候你有一個對象,根據某些條件需要調用一個方法或不同的方法。 例如,你有一個 car 對象,根據 driver.sleepy 的值,你可能想要把它開車(drive())或停車(park())。 如果司機的瞌睡程度超過6,我們需要在他開車時把車停下來。 以下是使用 if/else 條件語句實現此功能的例子: if (driver.sleepy > 6) { car.park() } else { car.drive() } 讓我們重寫這個例子,使它更加動態。 我們可以使用三元運算符動態選擇方法名,並將它作為字符串值獲取。 使用方括號,我們可以從對象的可用方法中選擇它: car[driver.sleepy > 6 ? 'park' : 'drive'] 通過上面的語句,我們獲取了方法的引用。我們可以通過追加括號來直接調用它: car[driver.sleepy > 6 ? 'park' : 'drive']()

在JavaScript中替換字符串的所有匹配項

了解在純JavaScript中替換字符串的所有匹配項的正確方法,從正則表達式到其他方法。 使用正則表達式 這個簡單的正則表達式可以完成任務: String.replace(/<TERM>/g, '') 這將執行區分大小寫的替換。 以下是一個示例,我將字符串phrase中單詞’dog’的所有匹配項替換為空字符串: const phrase = 'I love my dog! Dogs are great' const stripped = phrase.replace(/dog/g, '') stripped //"I love my ! Dogs are great" 要執行不區分大小寫的替換,請在正則表達式中使用i選項: String.replace(/<TERM>/gi, '') 示例: const phrase = 'I love my dog! Dogs are great' const stripped = phrase.replace(/dog/gi, '') stripped //"I love my ! s are great" 請記住,如果字符串包含一些特殊字符,它將無法正確處理正則表達式,因此建議使用此函數將字符串進行轉義(從MDN中取得): const escapeRegExp = (string) => { return string.replace(/[.\*+?^${}()|[\]\\]/g, '\\$&') } 使用split和join 另一種解決方案,儘管比正則表達式慢,是使用兩個JavaScript函數。...

在MongoDB集合中一次插入多個項目的方法

我有一個需求,需要在一個Node.js應用程式中一次插入多個項目到MongoDB集合中。 這是我所做的: const mongo = require('mongodb').MongoClient const url = 'mongodb://localhost:27017' let db, jobs mongo.connect( url, { useNewUrlParser: true, useUnifiedTopology: true, }, (err, client) => { if (err) { console.error(err) return } db = client.db('myapp') jobs = db.collection('jobs') const data = [{...}, {...}] jobs.insertMany(data) } ) 我將一個物件陣列傳遞給我想要填充的集合,然後在該集合上調用insertMany()方法。

在MySQL上創建用戶

一個快速的逐步指南,介紹如何在MySQL上創建用戶。 在安裝MySQL之後,您將擁有 root 用戶。 這是您可能使用的用戶來測試MySQL是否正常工作,但不應該將其用作其他用途的用戶。 為什麼呢?因為它具有過於強大的權限。 有了強大的權力就有了巨大的責任(說的是蜘蛛俠的叔叔)。 特別是,如果犯錯,就會有巨大的危險。 相反,您應該創建特定用戶,這些用戶只有執行其工作所需的權限,並且不再多。 與使用Linux或任何Unix系統一樣,您不希望使用 root 用戶,而是使用您自己的用戶帳戶。 要創建新用戶,使用 root 用戶連接到MySQL: mysql -u root -p 然後使用以下命令: CREATE USER '<username>'@'localhost' IDENTIFIED BY '<password>'; 例如,要創建一個名為 test_user,密碼為 test_password12A 的用戶,運行以下命令: CREATE USER 'test_user'@'localhost' IDENTIFIED BY 'test_password12A'; 命令應返回一行顯示 Query OK, 0 rows affected (X.XX sec): 如果您使用了無效密碼,系統將返回類似於 ERROR 1819 (HY000): Your password does not satisfy the current policy requirements 的錯誤消息。 在這種情況下,錯誤消息表示密碼不夠複雜,因為安裝MySQL時我告訴它使用某個密碼策略。 太好了!現在已經創建了用戶,我們可以使用該用戶連接到MySQL。 從命令行退出,只需輸入 QUIT,然後輸入: mysql -u test_user -p 現在如果我嘗試創建一個數據庫,將收到一個錯誤消息 ERROR 1044 (42000): Access denied for user 'test_user'@'localhost' to database 'testing':...

在Netlify上托管靜態網站的教程

發現Netlify,一個非常適合靜態網站的優秀托管服務,它還有一個很好的免費計劃、免費CDN並且運行非常快速。 我把我的博客托管在Netlify上。 我一段時間前轉移,我的前一個托管服務遇到了一些問題,導致我的網站在幾個小時內無法訪問,所以在等待它恢復上線期間,我尋找了一個快速的方式將其還原,並在Netlify上創建了一個複本。 由於這個博客使用的是Hugo,它是一個靜態網站生成器,所以我不需要太多工作將博客遷移到新的托管服務上。我只需要一個可以提供HTML文件的地方,而這幾乎是地球上的任何一個托管服務都能做到的。 我開始尋找最適合靜態網站的平台,有一些平台在我眼中脫穎而出,但最終我選擇了Netlify,並且很高興我這麼做了。 介紹Netlify 在我嘗試之前,有一些讓我留下了極好印象的事情。 首先,免費計劃非常豐富,無論是免費還是商業項目都可以享有100GB的每月免費帶寬,對於一個只有一些圖片的靜態網站來說,這是一個非常寬敞的空間。 它們提供全球CDN,以確保速度不成問題,即使在遠離中央位置服務器的大陸上也是如此。 你可以將你的DNS nameserver 指向Netlify,他們會為你處理一切,並且提供一個非常漂亮的界面來設置高級需求。 它們當然支援自訂域名和HTTPS。 從Firebase過來,我期望能夠以一種對程序員友好的方式來管理部署,但我發現Netlify在處理每個靜態網站生成器方面甚至更好。 Netlify和Hugo 我使用的是Hugo,在本地我使用它內建的工具hugo server運行服務器,該工具會在每次更改時重新構建所有HTML文件,並且默認運行一個HTTP服務器,端口為1313。 為了生成靜態網站,我需要運行hugo,這會在public/文件夾中創建一系列的文件。 在Firebase的情況下,我採用了這個方法:我運行hugo來創建文件,然後運行firebase deploy,配置它將public/文件夾的內容推送到Google服務器。 然而,在Netlify的情況下,我將它連接到了我私有的GitHub存儲庫,並且每次我推送到我告訴Netlify同步的主分支時,Netlify都會啟動新的部署,變更將在幾秒鐘內生效。 提示:如果你在Netlify上使用Hugo,請確保在netlify.toml中設置HUGO_VERSION為最新的Hugo穩定版本,因為默認版本可能比較舊(截至目前為止)並且不支援最新的功能,例如後綴束。這是我的netlify.toml配置文件。 如果你覺得這不是什麼新鮮事,你是正確的,因為這在自己的服務器上並不難實現(我在其他沒有托管在Netlify上的網站上也這麼做),但這裡有一些新鮮事情:你可以預覽GitHub(或GitLab、或BitBucket)的任何分支/PR,同時你的主站點仍然運行並顯示“穩定”的內容。 另一個很酷的功能是可以在2個不同的Git分支上進行A/B測試。 Netlify為靜態網站提供的高級功能 靜態網站的顯而易見的限制是不能執行任何服務器端操作,這和你從傳統CMS(如WordPress)中期望的功能不一樣。 這既是一個優勢(因為安全問題較少),也是一個你可以實現的功能的限制。 一個博客並不復雜,你可以使用像Disqus或其他類似服務來添加評論功能。 或者,你可以通過嵌入第三方應用程序(如Wufoo或Google Forms)生成的表單來添加表單。 Netlify提供了一套工具來處理表單,驗證用戶,甚至部署和管理Lambda函數。 需要在發布之前對網站進行密碼保護?✅ 需要處理CORS?✅ 需要進行301重定向?✅ 需要為你的SPA進行預渲染?✅ 我只是觸及了Netlify提供的功能的表面,而沒有借助第三方服務,希望我給你提供了一個嘗試Netlify的理由。 預覽分支 GitHub的集成和拉取請求一起工作得很好。 每次你推送一個拉取請求,Netlify就會在一個特定的URL上部署該分支,你可以與你的團隊共享這個URL,或者與任何你想共享的人共享。 這裡,我提出了一個拉取請求,以預覽博客文章,但只在我的公共博客上不可用: Netlify立即捕捉到它,並自動部署它🎉 點擊鏈接會將您指向一個特殊的URL,讓您可以預覽該分支的網站版本。

在Netlify上自動觸發部署

我有一份定期發布在我的博客上的文章清單。以下是我如何透過IFTTT每天早上自動觸發我的Hugo靜態網站部署在Netlify上的方法。 注意:這個方法不僅適用於Netlify,也適用於其他提供手動部署Webhooks的服務供應商。 我有一份定期發布在我的博客上的文章清單,而我試著提前撰寫幾天的內容,為我無法寫作的時候或是需要休息的時候留出空間。 我認為保持一致性對於保持工作的動力很重要。過去兩個月,我每週一至週六都有發布文章,且我未來也想繼續這樣做,因為我真的很喜歡寫作。 我使用的是 Hugo 靜態網站生成器,並且托管在 Netlify 上。 這組工具組合非常棒,對於博客的設置我非常滿意。 今天我在山上遠足時,突然意識到已經超過我通常發布文章的時間,而我之前已經安排好的博客文章也沒有發布。 使用 Hugo,我可以設定一個未來的發布日期,當使用 hugo CLI 命令重新構建網站時,這篇文章不會包含在生成的 HTML 中,因為它是未來的文章。 Netlify 有這個很不錯的概念,在他們的伺服器上構建 Hugo 網站,所以我只需要觸發一個新的部署。通常情況下,當我將任何內容推送到 GitHub 時,Netlify 會自動警報並在一分鐘內進行部署。 但在這種情況下,我需要手動觸發Netlify上的部署,所以我使用iPhone登錄並點擊“觸發部署”。 這個動作在服務器端使用Hugo重建靜態網站,我只需將手機放回口袋。 博客文章上線了🎉,我只需在Twitter上發一條推文。 在步行時,我意識到我可以自動化所有這些工作。 我只需要每天早上9點自動觸發一個部署。於是我在Netlify界面上尋找他們是否有任何定時循環部署的自動化功能。雖然沒有這樣的功能,但他們有一個WebHook端點。 因此,我尋找了一些可以每天對WebHook進行POST設置的工具。 我使用了Zapier(也可以),但之後轉用了 IFTTT,因為它可以免費提供相同的功能。 在Netlify上,我建立了一個WebHook URL 這給了我一個自定義的URL來呼叫: 我在IFTTT上創建了一個每天早上8點提醒的"applet": 並且在其中設定一個Web請求來觸發Netlify上的部署鉤子。 現在,我只需要創建內容,按計劃日期將其推送到GitHub,就不用再擔心手動部署了!🎉 👨🏼‍💻

在Node.js中解析JSON

如何從字符串解析JSON,以及如何在Node.js中讀取JSON文件 如果您有一個字符串作為一部分的JSON數據,最好的方法是使用JavaScript標準的JSON.parse方法來解析數據。自ECMAScript 5以來,這個方法已經提供給V8,這是Node.js所使用的JavaScript引擎。 示例: const data = '{ "name": "Flavio", "age": 35 }' try { const user = JSON.parse(data) } catch(err) { console.error(err) } 請注意,JSON.parse是同步的,所以JSON文件越大,你的程序執行時間也會越長,因為需要阻塞程序執行直到解析完成。 你可以通過將其放在一個promise和setTimeout調用中,以異步方式處理JSON。這確保解析在事件循環的下一次迭代中進行。 const parseJsonAsync = (jsonString) => { return new Promise(resolve => { setTimeout(() => { resolve(JSON.parse(jsonString)) }) }) } const data = '{ "name": "Flavio", "age": 35 }' parseJsonAsync(data).then(jsonData => console.log(jsonData)) 如果您的JSON數據是存在文件中的,您首先需要讀取它。 一種非常簡單的方法是使用require(): const data = require('./file.json') 由於你使用了.json擴展名,所以require()足夠聰明,會自動解析JSON數據到data對象中。 唯一的一個缺點是文件讀取是同步的方式進行的。此外,require()的結果會被緩存,所以如果您因為更新了文件而再次調用它,直到程序退出之前,您將無法獲取新的內容。 這個功能用於使用JSON文件作為應用程序配置的一部分,這是一個完全有效的使用場景。 您還可以手動讀取文件,使用fs.readFileSync: const fs = require('fs') const fileContents = fs....

在Node.js中遞迴獲取資料夾中的所有文件

你如何在Node.js中列出資料夾中的所有文件? 我有一個需求,需要遞迴地獲取資料夾中的所有文件。 我發現最好的方法是安裝glob庫: npm install glob 我想在content/post資料夾中查找所有的index.md文件,每個文件都在自己的目錄結構中,可能在多個子文件夾中: content/post/first/index.md content/post/second/index.md content/post/another/test/index.md 以下是我實現的方式: const glob = require('glob') const rootFolder = 'content/post' glob(rootFolder + '/\*\*/index.md', (err, files) => { if (err) { console.log('Error', err) } else { console.log(files) } })