摘要:系列系列簡單模擬語法一系列合成事件與二系列算法實現分析三系列從到再到四系列與部分源碼解析五系列從使用了解的各種使用方案六的誕生他是的一種擴展語法。這個函數接受組件的實例或元素作為參數,以存儲它們并使它們能被其他地方訪問。
React系列
React系列 --- 簡單模擬語法(一)
React系列 --- Jsx, 合成事件與Refs(二)
React系列 --- virtualdom diff算法實現分析(三)
React系列 --- 從Mixin到HOC再到HOOKS(四)
React系列 --- createElement, ReactElement與Component部分源碼解析(五)
React系列 --- 從使用React了解Css的各種使用方案(六)
他是 JavaScrip 的一種擴展語法。 React 官方推薦使用這種語法來描述 UI 信息。JSX 可能會讓你想起某種模板語言,但是它具有 JavaScrip 的全部能力
JSX 執行更快,因為它在編譯為 JavaScript 代碼后進行了優化。
它是類型安全的,在編譯過程中就能發現錯誤。
使用 JSX 編寫模板更加簡單快速。
編譯本質上來講,JSX 只是為 React.createElement(component, props, ...children) 方法提供的語法糖
123456
"use strict"; React.createElement("div", { className: "num", index: 1 }, React.createElement("span", null, "123456"));
具體效果可以在此體驗
這就是為什么盡管你看不到里面使用過React,但是如果你不引入模塊的話JSX會報錯.
JSX原理從上面的編譯代碼來看,JSX最終包含的信息其實分別是: 元素標簽, 元素屬性, 子元素.如果用Javascript對象來表示的話:
{ tag: "div", attrs: { className: "num", index: 1}, children: [ { tag: "span", arrts: null, children: null } ] }
所以整個過程大概如下
至于為什么會有中間編譯成JS對象那一步而不直接編譯成Dom元素.
除了普通頁面還可能渲染到canvas或者原生App(React Native了解一下)
后面的diff比較需要用到
事件處理React的事件是基于SyntheticEvent的實例實現模擬跨瀏覽器原生事件一樣的接口,包括stopPropagation()和preventDefault(),期望事件的行為跨瀏覽器是相同的.甚至兼容直達IE8.每個SyntheicEvent對象都有如下屬性:
基礎科普boolean bubbles boolean cancelable DOMEventTarget currentTarget boolean defaultPrevented number eventPhase boolean isTrusted DOMEvent nativeEvent void preventDefault() boolean isDefaultPrevented() void stopPropagation() boolean isPropagationStopped() DOMEventTarget target number timeStamp string type
在JavaScript中,事件的觸發實質上是要經過三個階段:事件捕獲、目標對象本身的事件處理和事件冒泡.
stopPropagation(): 停止事件冒泡
preventDefault(): 阻止默認行為
return false: 實際上使用這個的時候會做三件事
event.preventDefault();
event.stopPropagation();
停止回調函數執行并立即返回。
React是怎么管理事件系統的?出于性能原因.React會通過池方式復用SyntheicEvent對象,這意味著事件調用完成之后event.target上所有的屬性都會失效.意思就是當我們嘗試異步方式調用React事件,因為復用的原因,在事件回調執行完之后SyntheicEvent對象將不再存在,所以我們無法訪問其屬性.
function onClick(event) { console.log(event); // => nullified object. console.log(event.type); // => "click" const eventType = event.type; // => "click" setTimeout(function() { console.log(event.type); // => null console.log(eventType); // => "click" }, 0); // Won"t work. this.state.clickEvent will only contain null values. this.setState({clickEvent: event}); // You can still export event properties. this.setState({eventType: event.type}); }
比較常見的例子就是setState方法.
解決方案event.persist()
事件回調中調用event.persist()方法,這樣會在池中刪除合成事件,并且允許用戶代碼保留對事件的引用。
緩存屬性
我們可以將事件屬性存儲在事件函數并且傳遞給異步回調函數而不是直接在異步回調里訪問它們.
Debouncing a synthetic event handler(不知道怎么翻譯)
// Correct this.setState((prevState, props) => ({ counter: prevState.counter + props.increment }));合成事件注冊
源碼注釋
/** * Summary of `ReactBrowserEventEmitter` event handling: * * - Top-level delegation is used to trap most native browser events. This * may only occur in the main thread and is the responsibility of * ReactDOMEventListener, which is injected and can therefore support * pluggable event sources. This is the only work that occurs in the main * thread. * * - We normalize and de-duplicate events to account for browser quirks. This * may be done in the worker thread. * * - Forward these native events (with the associated top-level type used to * trap it) to `EventPluginHub`, which in turn will ask plugins if they want * to extract any synthetic events. * * - The `EventPluginHub` will then process each event by annotating them with * "dispatches", a sequence of listeners and IDs that care about that event. * * - The `EventPluginHub` then dispatches the events. * * Overview of React and the event system: * * +------------+ . * | DOM | . * +------------+ . * | . * v . * +------------+ . * | ReactEvent | . * | Listener | . * +------------+ . +-----------+ * | . +--------+|SimpleEvent| * | . | |Plugin | * +-----|------+ . v +-----------+ * | | | . +--------------+ +------------+ * | +-----------.--->|EventPluginHub| | Event | * | | . | | +-----------+ | Propagators| * | ReactEvent | . | | |TapEvent | |------------| * | Emitter | . | |<---+|Plugin | |other plugin| * | | . | | +-----------+ | utilities | * | +-----------.--->| | +------------+ * | | | . +--------------+ * +-----|------+ . ^ +-----------+ * | . | |Enter/Leave| * + . +-------+|Plugin | * +-------------+ . +-----------+ * | application | . * |-------------| . * | | . * | | . * +-------------+ . * . * React Core . General Purpose Event Plugin System */
DOM將事件傳給ReactEventListener注冊到document,然后分發到具體節點.EventPluginHub負責事件的存儲,合成事件以及池方式的實現創建和銷毀,后面是各種類型的合成事件模擬,交互通過ReactEventEmitter將原生的DOM事件轉化成合成的事件,觸發將對應操作推入隊列批量執行.因為瀏覽器會為每個事件的每個listener創建一個事件對象,上面提到的池方式復用就是為了解決高額內存分配的問題.
合成事件Clipboard Events
Composition Events
Keyboard Events
Focus Events
Form Events
Mouse Events
Pointer Events
Selection Events
Touch Events
UI Events
Wheel Events
Media Events
Image Events
Animation Events
Transition Events
Other Events
event其中事件都會被自動傳入一個event對象,是由React將瀏覽器原生的event對象封裝一下對外提供統一的API和屬性.
this因為React里調用傳入方法的時候并不是通過對象方法方式,而是直接通過函數調用,所以里面指向的this是null或者undefined.
一般傳入的時候需要手動用bind或者箭頭函數顯性綁定this指向
Refs & DOM這是一種用于訪問render方法中創建的DOM節點或React元素的方式.一般用于
處理表單,媒體控制
觸發強制動畫
集成第三方DOM庫
創建Refsclass MyComponent extends React.Component { constructor(props) { super(props) this.myRef = React.createRef() } render() { return } }訪問 Refs
const node = this.myRef.current;
如果用于一個普通HTMl元素時,React.createRef() 將接收底層 DOM 元素作為它的 current 屬性以創建 ref 。
當 ref 屬性被用于一個自定義類組件時,ref 對象將接收該組件已掛載的實例作為它的 current 。
你不能在函數式組件上使用 ref 屬性,因為它們沒有實例。
回調Refs不同于傳遞 createRef() 創建的 ref 屬性,你會傳遞一個函數。這個函數接受 React 組件的實例或 HTML DOM 元素作為參數,以存儲它們并使它們能被其他地方訪問。
class CustomTextInput extends React.Component { constructor(props) { super(props); this.textInput = null; this.setTextInputRef = element => { this.textInput = element; }; this.focusTextInput = () => { // 直接使用原生 API 使 text 輸入框獲得焦點 if (this.textInput) this.textInput.focus(); }; } componentDidMount() { // 渲染后文本框自動獲得焦點 this.focusTextInput(); } render() { // 使用 `ref` 的回調將 text 輸入框的 DOM 節點存儲到 React // 實例上(比如 this.textInput) return (); } }
如果是組件間傳遞回調形式的 refs如下:
function CustomTextInput(props) { return (無狀態組件中使用); } class Parent extends React.Component { render() { return (this.inputElement = el} /> ); } }
因為無狀態組件是不會被實例化的,但是我們可以用過一個變量訪問其中的組件或者dom元素組件的實例引用
function CustomTextInput(props) { let inputRef; return (inputRef = node} />); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106480.html
摘要:按鈕中使用原生事件中提供了很好的合成事件系統,但有時候也需要用到原生事件。而使用合成事件系統時則不需要,因為內部以及處理了。事件類型鍵盤事件焦點事件表單事件鼠標事件選擇事件觸摸事件事件動畫事件圖像事件媒體事件剪貼板事件上一篇開發教程六與 事件系統 Virtual DOM在內存中是以對象的形式存在的,如果想要在這些對象上添加事件的話,React是基于Virtual DOM實現了一個合成事...
摘要:系列系列簡單模擬語法一系列合成事件與二系列算法實現分析三系列從到再到四系列與部分源碼解析五系列從使用了解的各種使用方案六前言我們先不講什么語法原理先根據效果強行模擬語法使用實現一個簡易版的第一步我們先用類 React系列 React系列 --- 簡單模擬語法(一)React系列 --- Jsx, 合成事件與Refs(二)React系列 --- virtualdom diff算法實現分析...
摘要:個人感覺這與中的布局文件類似。其中的會被解析。中的標簽,由基礎庫提供。認為,我們的程序是一個狀態機。支持我們更改狀態,從而引起視圖的變化。綁定事件是放在中的。事件名稱直接寫為標簽的屬性,其值則是對應的事件處理函數。 這一系列課程說了很多關于react-native的知識,都是有關于樣式,底層,環境等知識的,現在我們來學習一下reactjs的基礎知識。我們的代碼,我們創建的組件的相關知識...
閱讀 3278·2023-04-26 00:57
閱讀 600·2021-10-08 10:05
閱讀 1345·2021-09-08 09:36
閱讀 4147·2021-08-12 13:31
閱讀 2542·2019-08-30 15:55
閱讀 2237·2019-08-30 15:55
閱讀 1013·2019-08-30 15:55
閱讀 2684·2019-08-29 13:17