React Router:為什麼 useLocation 和 useHistory 可能會返回 undefined

我在使用 React Router 時,使用了 useLocation 和 useHistory hooks 的地方卻都返回了 undefined。這真是讓我感到困惑。 const history = useHistory() const location = useLocation() 結果都返回了 undefined。 後來才發現,我在同一個組件中使用 useLocation 和 useHistory 並在 DOM 中添加 <Router>...</Router>。 然後我找到了這個 issue,解釋說我不能這樣做。 我需要將 <Router>...</Router> 的包裹組件提升一層。在我的情況下,我在 index.js 文件中進行了如下修改: import { BrowserRouter as Router } from 'react-router-dom' ... ReactDOM.render( <React.StrictMode> <Router> <App /> </Router> </React.StrictMode>, document.getElementById('root') )

React,在元素新增至 DOM 時將焦點設定至項目

如何在 React 中在元素新增至 DOM 時設定焦點? 我有一個包含簡單表單的模態對話框,其中只有一個 input 欄位,我希望當模態對話框由 React 添加到 DOM 時,該元素能夠自動獲得焦點。 我開始思考許多不同的方式來實現這樣的效果,或許使用 useEffect() 來在組件添加到 DOM 時觸發事件,或者使用 ref 屬性來創建對 DOM 元素的引用並調用其 focus() 方法。不過後來我意識到我想得太複雜了,只需要在元素上使用 HTML 的 autofocus 屬性就可以解決這個問題。 果然如此。請記住,在 JSX 中它是 autoFocus,F 是大寫的: <input autoFocus ...// 其他輸入欄位的屬性

referenceerror: window未定義,如何解決

了解如何修復“referenceerror: window未定義”錯誤。 在Node.js或類似Next.js的工具中,你可能會遇到這個錯誤。 window是瀏覽器提供的一個對象,在服務器端的JavaScript環境中不可用。 我在我的詳細的DOM 文檔物件模型指南中詳細介紹了window對象。 對於Node.js來說,沒有辦法解決這個問題 - 你必須找到使用window的特定位置,並重新檢查代碼以找出為什麼要訪問window對象。 你在後端環境中運行前端代碼。 在Next.js中,你可以通過將代碼包裝在條件語句中來解決這個問題。 該代碼在兩種情況下運行 - 前端情況下,當你使用鏈接訪問頁面時,以及如果你在頁面中引入了服務器端的代碼,例如通過運行getServerSideProps()。 在這種情況下,你可以將引用限制在一個條件語句中,檢查window對象是否可用,像這樣: if (typeof window !== 'undefined') { // 這裡`window`是可用的 } 這樣就可以解決你的問題,因為你只在瀏覽器環境中運行條件語句內的任何代碼。

Web Workers

學習使用 Web Workers 在背景中運行 JavaScript 代碼的方法。 介紹 Web Workers 的瀏覽器支持 創建 Web Worker 與 Web Worker 通信 使用 Web Worker 物件中的 postMessage 傳回訊息 多個事件監聽器 使用 Channel Messaging API Web Worker 的生命週期 在 Web Worker 中加載庫 Web Worker 可用的 API Introduction JavaScript 是單線程的,無法同時並行運行。 這很好,因為我們不需要擔心並發編程中可能發生的一系列問題。 由於這個限制,JavaScript 代碼從一開始就被迫高效,否則用戶會有不好的體驗。昂貴的操作應該是異步的,以避免阻塞線程。 隨著 JavaScript 應用程序的需求越來越多,這在某些場景中開始成為一個問題。 Web Workers 在瀏覽器內引入了並行執行的可能性。 它們有幾個限制: 無法訪問 DOM:Window 對象和 Document 對象 它們可以通過消息與主 JavaScript 程序進行通信 它們需要從相同的源頭(域名、端口和協議)加載 如果使用文件協議(file://)提供頁面,它們就不能工作 Web Worker 的全局作用域是一個名為 WorkerGlobalScope 的對象,而不是在主線程中的 Window。 Browser support for Web Workers 非常好!...

事件冒泡和事件捕獲

了解JavaScript中的事件冒泡和事件捕獲的工作原理 冒泡和捕獲是DOM事件用於傳播的兩種模型。 假設您的DOM結構如下: <div id="container"> <button>Click me</button> </div> 您希望在用戶點擊“button”時進行跟踪,並且有兩個事件監聽器,一個在button上,另一個在#container上。 請記住,除非您停止事件的傳播(參見後面的內容),否則對子元素的點擊事件將始終傳播到其父元素。 這些事件監聽器將按照順序調用,並且該順序由事件的冒泡/捕獲模型決定。 冒泡意味著事件從被點擊的項目(子項)向上傳播到其所有父層樹,從最近的父層開始。 在我們的示例中,button上的處理程序將在#container上的處理程序之前觸發。 捕獲則相反:外部事件處理程序在更具體的處理程序(例如button上的處理程序)之前觸發。 默認情況下,所有事件都會冒泡。 您可以通過將第三個參數應用於addEventListener並將其設置為true來選擇採用事件捕獲: document.getElementById('container').addEventListener( 'click', () => { //window loaded }, true ) 請注意,首先運行所有捕獲事件處理程序,然後運行所有冒泡事件處理程序。 順序遵循以下原則:DOM從Window對象開始,遍歷所有元素並尋找被點擊的項目。在此過程中,調用與事件關聯的任何事件處理程序(捕獲階段)。 一旦到達目標,它然後從父層樹重複此過程,直到Window對象,再次調用事件處理程序(冒泡階段)。

在瀏覽器中使用原生 JavaScript 實現事件委派

在 jQuery 中,我最喜歡的功能之一就是事件委派。特別是.on()方法。 我們先選擇一個 DOM 元素,然後使用.on()來附加一個事件處理程序,該處理程序將在該元素的特定子元素上執行。 為什麼這很有用?因為如果你動態地將元素添加到 DOM 中,通過.on()注册的單個事件監聽器將對所有子元素都有效,包括在註冊事件處理程序之後添加到 DOM 中的子元素。 假設你有一個表格。在表格內部,我們有一組行,每個行都有一個帶有點擊處理程序的按鈕。 在 DOM 加載時,你註冊一個事件監聽器: document.addEventListener('DOMContentLoaded', () => { const buttons = document.querySelectorAll('button') for (const button of buttons) { button.addEventListener(...) } }) 但如果我們向表格中添加一個新的行,我們還必須記得註冊一個新的事件監聽器。 那麼我們如何使用原生 JavaScript 實現相同的功能呢? 我們可以創建一個 on 函數,該函數接受三個參數:包裹元素的選擇器,事件類型(例如 'click' 字符串),以及子元素的選擇器字符串,用於匹配包裹元素的後代元素。在這個函數中,我們首先創建一個循環,然後對每個與我們的包裹元素選擇器匹配的元素添加事件監聽器(因此它可以應用於多個包裹元素)。 然後,如果事件的目標與我們的子元素選擇器(函數的第三個參數)匹配,我們調用作為第四個參數傳遞的回調函數,並將事件作為參數傳遞: const on = (selector, eventType, childSelector, eventHandler) => { const elements = document.querySelectorAll(selector) for (element of elements) { element.addEventListener(eventType, eventOnElement => { if (eventOnElement.target.matches(childSelector)) { eventHandler(eventOnElement) } }) } } 這是我們如何調用這個函數:...

在處理 DOM 時,時間的重要性

在與我的編程訓練班學生一起工作時,我幫助了其中一些人解決了一個問題:時間。 特別是,有一件事起初可能並不明顯。 當您存取 DOM 元素的值並將其存儲到變量中時,當 DOM 元素更改時,該變量將 不會 更新為新值。 假設您在表單中有一個輸入字段 <input id="temperature">,並以以下方式獲取其值: const temperature = document.querySelector('input#temperature').value temperature 變數會獲取瀏覽器在執行此語句時輸入字段的狀態,並且值將永遠保持不變。 這就是為什麼您不能像這樣操作: const temperature = document.querySelector('input#temperature').value document.querySelector('form') .addEventListener('submit', event => { //將溫度值發送到服務器 }) 而您需要在提交表單時訪問溫度值: document.querySelector('form') .addEventListener('submit', event => { const temperature = document.querySelector('input#temperature').value //將溫度值發送到服務器 }) 或者,您可以將輸入字段的 引用 存儲在變量中,然後在提交表單時使用它來訪問其值: const temperatureElement = document.querySelector('input#temperature') document.querySelector('form') .addEventListener('submit', event => { const temperature = temperatureElement.value //將溫度值發送到服務器 })

如何使用 insertAdjacentHTML

insertAdjacentHTML 是一個非常酷的 DOM 方法,我們可以在任何 DOM 元素上調用它來向頁面添加新的內容。 這是一種很好且靈活的插入新內容的方式。 該方法在一個元素上被調用,並接受兩個參數:位置和包含 HTML 的字符串。 以下是一個示例: const item = `<div> test </div> ` document.querySelector('#container').insertAdjacentHTML('afterend', item) 請注意這裡的 afterend 字符串。 它表示我們要將 HTML 添加到容器中的位置。 我們有四個可能的位置: beforebegin:在元素之前 afterbegin:在元素的第一個子元素之前 beforeend:在元素的最後一個子元素之後 afterend:在元素之後 以下是我們如何向列表添加新項目的示例: document.querySelector('ul').insertAdjacentHTML('beforeend', '<li>item</li>')

如何使用 querySelectorAll 循環遍歷 DOM 元素

總結: 使用 for..of 循環 querySelectorAll() 方法在 document 上運行,返回滿足選擇器查詢的 DOM 元素列表。 它返回的是一個元素列表,而不是數組,而是一個 NodeList 對象。 最簡單的遍歷結果的方法是使用 for..of 循環: for (const item of document.querySelectorAll('.buttons')) { //...做一些事情 }

如何使用JavaScript將圖片添加到DOM

最近我需要以程式的方式將圖片添加到DOM(也就是HTML頁面)中,這篇文章將告訴你如何以動態的方式實現。 首先,我們使用Document物件的createElement方法來創建一個img元素: const image = document.createElement('img') 然後,我們設置圖片的src屬性: image.src = '/picture.png' (你可以使用相對或絕對URL,就像在常規的HTML img 標籤中一樣) 接下來,我們找到要添加圖片的容器元素,並將其作為參數傳遞給appendChild()方法: document.querySelector('.container').appendChild(image) 就這樣,圖片就成功地被添加到DOM中了。