React 事件

学习如何在React应用中与事件进行交互 React提供了一种简单的方式来管理事件。准备与addEventListener说再见吧。 在关于状态的上一篇文章中,你看到了这个例子: const CurrencySwitcher = props => { return ( <button onClick={props.handleChangeCurrency}> 当前货币是{props.currency}。更改它! </button> ) } 如果你已经使用JavaScript一段时间了,这就像是普通的JavaScript事件处理程序,只不过这次你是在JavaScript中定义一切,而不是在HTML中,并且你传递的是一个函数,而不是一个字符串。 实际的事件名称有一点不同,因为在React中你使用驼峰命名法,所以onclick变成了onClick,onsubmit变成了onSubmit。 作为参考,这是一个将JavaScript事件混合在一起的老派HTML: <button onclick="handleChangeCurrency()">...</button> 事件处理函数 在组件类中将事件处理函数定义为方法是一种惯例: class Converter extends React.Component { handleChangeCurrency = event => { this.setState({ currency: this.state.currency === '€' ? '$' : '€' }) } } 所有的处理函数都接收一个符合W3C UI Events规范的事件对象,可跨浏览器使用。 在方法中绑定this 不要忘记绑定方法。ES6类的方法默认情况下不绑定this。这意味着如果你不将方法定义为箭头函数,this将不会被定义: class Converter extends React.Component { handleClick = e => { /\* ... \*/ } //... } 使用Babel的属性初始化语法(在create-react-app中默认启用)时,或者需要在构造函数中手动绑定: class Converter extends React....

React入門

React視圖庫介紹 什麼是React? React是一個旨在簡化視覺界面開發的JavaScript庫。 它是在Facebook開發並於2013年釋出的,是一些最廣泛使用的應用程序的引擎,為Facebook和Instagram等眾多應用程序提供動力。 它的主要目標是通過將UI分成一系列組件,使得在任何時間點都可以輕松理解界面及其狀態。 React為什麼如此受歡迎? React在前端Web開發領域引起了轟動。為什麼? 比其他替代方案更簡單 在React宣布時,Ember.js和Angular 1.x是主要的框架選擇。這兩個框架對代碼施加了許多約定,因此不方便移植現有應用程序。React選擇非常容易集成到現有項目中,因為這是Facebook在將其引入現有代碼庫時所必須做的。此外,這兩個框架提供了太多內容,而React只選擇實現了View層而不是完整的MVC堆棧。 完美的時機 當時,Google宣布了Angular 2.x,隨之而來的是不向後兼容的重大更改。從Angular 1轉到Angular 2就像轉到不同的框架,因此這個因素,再加上React承諾的執行速度改進,使得開發人員渴望嘗試它。 得到Facebook的支持 如果React成為成功的項目,得到Facebook的支持顯然是一個好處。 Facebook目前對React非常感興趣,認為它的開源價值,對於所有在自己項目中使用React的開發人員來說,這是一個巨大的加分點。 React學習起來簡單嗎? 雖然我說React比替代框架更簡單,但深入研究React仍然很複雜,主要是因為可以與React集成的相關技術,如Redux和GraphQL。 React本身具有非常小的API,你只需要理解4個概念就可以入門: 組件 JSX 狀態 屬性

React高階元件

了解什麼是高階元件,以及在開發React應用程式時它們的用途。 你可能對JavaScript中的高階函式已經很熟悉了。這是指接受函式作為參數和/或回傳函式的函式。 兩個範例是Array.map()和Array.filter()。 在React中,我們將此概念擴展到元件,因此我們有了高階元件(HOC),當元件接受元件作為輸入並將元件作為輸出時。 一般來說,高階元件可以讓你創建可組合和可重用的程式碼,並提供更好的封裝性。 我們可以使用高階元件來向元件的狀態或屬性添加方法或屬性,例如Redux儲存。 當你想要增強現有元件、操作狀態或屬性,或者操作它的渲染標記時,你可能會想要使用高階元件。 通常,在高階元件前面加上with字串是一個常見的慣例(這只是一個慣例,並不是強制性的),所以如果你有一個Button元件,它的高階元件對應名稱應該叫作withButton。 讓我們創建一個高階元件。 最簡單的高階元件範例就是不做任何改變地返回元件: const withElement = Element => () => <Element /> 讓我們增加點有用性,將一個額外的屬性(顏色)加到此元素上,除了它原本就有的所有屬性: const withColor = Element => props => <Element {...props} color="red" /> 然後,在元件的JSX中使用這個高階元件: const Button = () => { return <button>test</button> } const ColoredButton = withColor(Button) 最後,在我們應用程式的JSX中渲染包裝後的按鈕元件: function App() { return ( <div className="App"> <h1>Hello</h1> <ColoredButton /> </div> ) } 雖然這只是一個非常簡單的範例,但希望你能掌握高階元件的概念,並將這些概念應用於更複雜的情境中。

requestAnimationFrame()指南

學習使用API以可預測的方式執行動畫並安排事件 requestAnimationFrame()是一個相對較新的瀏覽器API。它提供一種更可預測的方式來連接到瀏覽器的渲染循環。 目前,所有現代瀏覽器(包括IE 10+)都支援這個API。 它不是專門用於動畫的API,但這是它被最廣泛使用的領域。 JavaScript有一個事件循環(event loop)。它不斷運行以執行JavaScript。 在過去,使用setTimeout()或setInterval()執行動畫。你執行一點點動畫,然後使用setTimeout()在幾毫秒後重複執行這段代碼: const performAnimation = () => { //... setTimeout(performAnimation, 1000 / 60) } setTimeout(performAnimation, 1000 / 60) 或是 const performAnimation = () => { //... } setInterval(performAnimation, 1000 / 60) 你可以透過獲取timeout或interval的參考並將其清除來停止動畫: let timer const performAnimation = () => { //... timer = setTimeout(performAnimation, 1000 / 60) } timer = setTimeout(performAnimation, 1000 / 60) //... clearTimeout(timer) performAnimation()調用之間的1000 / 60間隔取決於顯示器的刷新頻率,大多數情況下是60 Hz(每秒重繪60次),因為由於其限制,如果顯示器無法顯示,執行重繪將是無用的。這導致我們有大約16.6毫秒的時間來顯示每一個幀。 這種方法的問題是,即使我們精確指定了這個間隔,瀏覽器可能忙於執行其他操作,我們的setTimeout調用可能不能及時進行重繪,並且將被延遲到下一個循環。 這很糟糕,因為我們丟失了一個幀,在下一個幀中,動畫將被執行兩次,使眼睛注意到不平滑的動畫。 在Glitch上的這個使用setTimeout()構建的動畫的示例中可以看到這個問題。 requestAnimationFrame是執行動畫的標準方式,儘管代碼看起來非常類似於setTimeout/setInterval的代碼,它的工作方式非常不同:...

Streams API(流式API)

使用流式API,我們可以在第一個位元抵達時,立即從網路或其他來源接收資源並處理它。 不必等待資源完全下載後再使用它,可以立即開始處理。 什麼是流? 首先遇到的例子是載入YouTube視頻 - 在您開始觀看它之前,您不必完全載入它。 或者是直播,您甚至不知道內容何時結束。 內容甚至不必結束,它可以無限生成。 Streams API(流API) Streams API允許我們處理這種類型的內容。 我們有兩種不同的流模式:從流程讀取和寫入流程。 可讀流在除了Internet Explorer之外的所有現代瀏覽器中都可用。 可寫流在Firefox和Internet Explorer中不可用。 一如既往,請參閱caniuse.com上有關此問題的最新信息。 讓我們從可讀流開始 可讀流 當涉及到可讀流時,我們有三種對象類別: ReadableStream ReadableStreamDefaultReader ReadableStreamDefaultController 我們可以使用ReadableStream對像來消耗流。 這是第一個可讀流的例子。Fetch API允許從網絡中獲取資源並將其作為流程提供。 const stream = fetch('/resource') .then(response => response.body) fetch響應的body屬性是ReadableStream對象實例。這就是我們的可讀流。 閱讀器 在ReadableStream對像上調用getReader()方法會返回ReadableStreamDefaultReader對像,即閱讀器。我們可以按如下方式獲取: const reader = fetch('/resource').then(response => response.body.getReader()) 我們按塊讀取數據,其中一個塊是一個位元組或一個類型化數組。將塊排入流程,並逐個塊讀取它們。 單個流程可以包含不同類型的块。 一旦我們有了ReadableStreamDefaultReader對象,我們可以使用read()方法訪問數據。 只要創建了閱讀器,流程就鎖定了,其他讀者不能從它獲取塊,直到我們在閱讀器上調用releaseLock()。 您可以使用tee()方法來實現這種效果,後面將更詳細介紹。 從可讀流讀取數據 一旦我們有了ReadableStreamDefaultReader對象實例,就可以從中讀取數據。 以下是如何按字節(由於CORS原因,您可以在打開了該頁面的DevTools窗口中執行此操作)逐個字節讀取flaviocopes.com網頁的首個块的數據的方法。 fetch('https://flaviocopes.com/') .then(response => { response.body .getReader() .read() .then(({value, done}) => { console.log(value) }) }) 如果你打開每組數組項,你會得到單個項目。這些都是以Uint8Array存儲的字元: 您可以使用Encoding API將這些字節轉換為字符: const decoder = new TextDecoder('utf-8') fetch('https://flaviocopes....

String padEnd()方法

了解JavaScript的字串 padEnd()方法的所有資訊 字串填充的目的是添加字元到字串,直到它達到指定的長度。 padEnd()在ES2017中引入,它會在字串的尾端添加這些字元。 padEnd(targetLength [, padString]) 使用範例: padEnd() ‘test’.padEnd(4) ‘test’ ‘test’.padEnd(5) ‘test ’ ‘test’.padEnd(8) ‘test ’ ‘test’.padEnd(8, ‘abcd’) ‘testabcd’ 參閱 padStart()。

String trim() 方法

了解 JavaScript 字串的 trim() 方法 從原始字串的開頭和結尾中移除空格並回傳新的字串 'Testing'.trim() //'Testing' ' Testing'.trim() //'Testing' ' Testing '.trim() //'Testing' 'Testing '.trim() //'Testing'

String valueOf() 方法

了解 JavaScript 字符串的 valueOf() 方法 返回当前 String 对象的字符串表示: const str = new String('Test') str.valueOf() //'Test' 同 toString()。

string.trimStart() 方法

了解 JavaScript 字串的 trimStart() 方法 從原始字串的開頭移除空白並回傳新的字串 'Testing'.trimStart() //'Testing' ' Testing'.trimStart() //'Testing' ' Testing '.trimStart() //'Testing ' 'Testing '.trimStart() //'Testing'

String的normalize()方法

了解JavaScript字符串的normalize()方法。 Unicode有四种主要的标准化形式:NFC、NFD、NFKC、NFKD。维基百科对此有很好的解释。 normalize()方法根据您指定的形式对字符串进行标准化,并将其作为参数传递给该方法(如果未设置参数,则默认为NFC)。 我将重用MDN的示例,因为我确信这是一个有效的用法,但我找不到其他示例: '\u1E9B\u0323'.normalize() //ẛ̣ '\u1E9B\u0323'.normalize('NFD') //ẛ̣ '\u1E9B\u0323'.normalize('NFKD') //ṩ '\u1E9B\u0323'.normalize('NFKC') //ṩ