成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

React系列 --- Jsx, 合成事件與Refs(二)

LiuZh / 1990人閱讀

摘要:系列系列簡(jiǎn)單模擬語(yǔ)法一系列合成事件與二系列算法實(shí)現(xiàn)分析三系列從到再到四系列與部分源碼解析五系列從使用了解的各種使用方案六的誕生他是的一種擴(kuò)展語(yǔ)法。這個(gè)函數(shù)接受組件的實(shí)例或元素作為參數(shù),以存儲(chǔ)它們并使它們能被其他地方訪問(wèn)。

React系列

React系列 --- 簡(jiǎn)單模擬語(yǔ)法(一)
React系列 --- Jsx, 合成事件與Refs(二)
React系列 --- virtualdom diff算法實(shí)現(xiàn)分析(三)
React系列 --- 從Mixin到HOC再到HOOKS(四)
React系列 --- createElement, ReactElement與Component部分源碼解析(五)
React系列 --- 從使用React了解Css的各種使用方案(六)

JSX的誕生

他是 JavaScrip 的一種擴(kuò)展語(yǔ)法。 React 官方推薦使用這種語(yǔ)法來(lái)描述 UI 信息。JSX 可能會(huì)讓你想起某種模板語(yǔ)言,但是它具有 JavaScrip 的全部能力

JSX 執(zhí)行更快,因?yàn)樗诰幾g為 JavaScript 代碼后進(jìn)行了優(yōu)化。

它是類型安全的,在編譯過(guò)程中就能發(fā)現(xiàn)錯(cuò)誤。

使用 JSX 編寫(xiě)模板更加簡(jiǎn)單快速。

編譯

本質(zhì)上來(lái)講,JSX 只是為 React.createElement(component, props, ...children) 方法提供的語(yǔ)法糖

123456
"use strict";

React.createElement("div", {
  className: "num",
  index: 1
}, React.createElement("span", null, "123456"));

具體效果可以在此體驗(yàn)

這就是為什么盡管你看不到里面使用過(guò)React,但是如果你不引入模塊的話JSX會(huì)報(bào)錯(cuò).

JSX原理

從上面的編譯代碼來(lái)看,JSX最終包含的信息其實(shí)分別是: 元素標(biāo)簽, 元素屬性, 子元素.如果用Javascript對(duì)象來(lái)表示的話:

{
  tag: "div",
  attrs: { className: "num", index: 1},
  children: [
    {
      tag: "span",
      arrts: null,
      children: null
    }
  ]
}

所以整個(gè)過(guò)程大概如下

至于為什么會(huì)有中間編譯成JS對(duì)象那一步而不直接編譯成Dom元素.

除了普通頁(yè)面還可能渲染到canvas或者原生App(React Native了解一下)

后面的diff比較需要用到

事件處理

React的事件是基于SyntheticEvent的實(shí)例實(shí)現(xiàn)模擬跨瀏覽器原生事件一樣的接口,包括stopPropagation()preventDefault(),期望事件的行為跨瀏覽器是相同的.甚至兼容直達(dá)IE8.每個(gè)SyntheicEvent對(duì)象都有如下屬性:

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
基礎(chǔ)科普

在JavaScript中,事件的觸發(fā)實(shí)質(zhì)上是要經(jīng)過(guò)三個(gè)階段:事件捕獲、目標(biāo)對(duì)象本身的事件處理和事件冒泡.

stopPropagation(): 停止事件冒泡

preventDefault(): 阻止默認(rèn)行為

return false: 實(shí)際上使用這個(gè)的時(shí)候會(huì)做三件事

event.preventDefault();

event.stopPropagation();

停止回調(diào)函數(shù)執(zhí)行并立即返回。

React是怎么管理事件系統(tǒng)的?

出于性能原因.React會(huì)通過(guò)池方式復(fù)用SyntheicEvent對(duì)象,這意味著事件調(diào)用完成之后event.target上所有的屬性都會(huì)失效.意思就是當(dāng)我們嘗試異步方式調(diào)用React事件,因?yàn)閺?fù)用的原因,在事件回調(diào)執(zhí)行完之后SyntheicEvent對(duì)象將不再存在,所以我們無(wú)法訪問(wèn)其屬性.

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});
}

比較常見(jiàn)的例子就是setState方法.

解決方案

event.persist()

事件回調(diào)中調(diào)用event.persist()方法,這樣會(huì)在池中刪除合成事件,并且允許用戶代碼保留對(duì)事件的引用。

緩存屬性

我們可以將事件屬性存儲(chǔ)在事件函數(shù)并且傳遞給異步回調(diào)函數(shù)而不是直接在異步回調(diào)里訪問(wèn)它們.


Debouncing a synthetic event handler(不知道怎么翻譯)

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

合成事件注冊(cè)

源碼注釋

/**
 * 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注冊(cè)到document,然后分發(fā)到具體節(jié)點(diǎn).EventPluginHub負(fù)責(zé)事件的存儲(chǔ),合成事件以及池方式的實(shí)現(xiàn)創(chuàng)建和銷毀,后面是各種類型的合成事件模擬,交互通過(guò)ReactEventEmitter將原生的DOM事件轉(zhuǎn)化成合成的事件,觸發(fā)將對(duì)應(yīng)操作推入隊(duì)列批量執(zhí)行.因?yàn)闉g覽器會(huì)為每個(gè)事件的每個(gè)listener創(chuàng)建一個(gè)事件對(duì)象,上面提到的池方式復(fù)用就是為了解決高額內(nèi)存分配的問(wèn)題.

合成事件

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

其中事件都會(huì)被自動(dòng)傳入一個(gè)event對(duì)象,是由React將瀏覽器原生的event對(duì)象封裝一下對(duì)外提供統(tǒng)一的API和屬性.

this

因?yàn)镽eact里調(diào)用傳入方法的時(shí)候并不是通過(guò)對(duì)象方法方式,而是直接通過(guò)函數(shù)調(diào)用,所以里面指向的this是null或者undefined.

一般傳入的時(shí)候需要手動(dòng)用bind或者箭頭函數(shù)顯性綁定this指向

Refs & DOM

這是一種用于訪問(wèn)render方法中創(chuàng)建的DOM節(jié)點(diǎn)或React元素的方式.一般用于

處理表單,媒體控制

觸發(fā)強(qiáng)制動(dòng)畫(huà)

集成第三方DOM庫(kù)

創(chuàng)建Refs
class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    this.myRef = React.createRef()
  }
  render() {
    return 
} }
訪問(wèn) Refs
const node = this.myRef.current;

如果用于一個(gè)普通HTMl元素時(shí),React.createRef() 將接收底層 DOM 元素作為它的 current 屬性以創(chuàng)建 ref 。

當(dāng) ref 屬性被用于一個(gè)自定義類組件時(shí),ref 對(duì)象將接收該組件已掛載的實(shí)例作為它的 current 。

你不能在函數(shù)式組件上使用 ref 屬性,因?yàn)樗鼈儧](méi)有實(shí)例。

回調(diào)Refs

不同于傳遞 createRef() 創(chuàng)建的 ref 屬性,你會(huì)傳遞一個(gè)函數(shù)。這個(gè)函數(shù)接受 React 組件的實(shí)例或 HTML DOM 元素作為參數(shù),以存儲(chǔ)它們并使它們能被其他地方訪問(wèn)。

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = null;

    this.setTextInputRef = element => {
      this.textInput = element;
    };

    this.focusTextInput = () => {
      // 直接使用原生 API 使 text 輸入框獲得焦點(diǎn)
      if (this.textInput) this.textInput.focus();
    };
  }

  componentDidMount() {
    // 渲染后文本框自動(dòng)獲得焦點(diǎn)
    this.focusTextInput();
  }

  render() {
    // 使用 `ref` 的回調(diào)將 text 輸入框的 DOM 節(jié)點(diǎn)存儲(chǔ)到 React
    // 實(shí)例上(比如 this.textInput)
    return (
      
); } }

如果是組件間傳遞回調(diào)形式的 refs如下:

function CustomTextInput(props) {
  return (
    
); } class Parent extends React.Component { render() { return ( this.inputElement = el} /> ); } }
無(wú)狀態(tài)組件中使用

因?yàn)闊o(wú)狀態(tài)組件是不會(huì)被實(shí)例化的,但是我們可以用過(guò)一個(gè)變量訪問(wèn)其中的組件或者dom元素組件的實(shí)例引用

function CustomTextInput(props) {
  let inputRef;
  return (
    
inputRef = node} />
); }

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/106480.html

相關(guān)文章

  • React

    摘要:基礎(chǔ)創(chuàng)建虛擬參數(shù)元素名稱,例如參數(shù)屬性集合,例如,,,從參數(shù)開(kāi)始,表示該元素的子元素,通常這些元素通過(guò)創(chuàng)建,文本文件可以直接插入嘻嘻哈哈這是渲染器,將元素渲染到頁(yè)面中。 React簡(jiǎn)介 FeceBook開(kāi)源的一套框架,專注于MVC的視圖V模塊。實(shí)質(zhì)是對(duì)V視圖的一種實(shí)現(xiàn)。 React框架的設(shè)計(jì)沒(méi)有過(guò)分依賴于某個(gè)環(huán)境,它自建一套環(huán)境,就是virtual DOM(虛擬DOM)。 提供基礎(chǔ)AP...

    hlcc 評(píng)論0 收藏0
  • react開(kāi)發(fā)教程(七)React事件系統(tǒng)

    摘要:按鈕中使用原生事件中提供了很好的合成事件系統(tǒng),但有時(shí)候也需要用到原生事件。而使用合成事件系統(tǒng)時(shí)則不需要,因?yàn)閮?nèi)部以及處理了。事件類型鍵盤事件焦點(diǎn)事件表單事件鼠標(biāo)事件選擇事件觸摸事件事件動(dòng)畫(huà)事件圖像事件媒體事件剪貼板事件上一篇開(kāi)發(fā)教程六與 事件系統(tǒng) Virtual DOM在內(nèi)存中是以對(duì)象的形式存在的,如果想要在這些對(duì)象上添加事件的話,React是基于Virtual DOM實(shí)現(xiàn)了一個(gè)合成事...

    walterrwu 評(píng)論0 收藏0
  • React系列 --- 簡(jiǎn)單模擬語(yǔ)法(一)

    摘要:系列系列簡(jiǎn)單模擬語(yǔ)法一系列合成事件與二系列算法實(shí)現(xiàn)分析三系列從到再到四系列與部分源碼解析五系列從使用了解的各種使用方案六前言我們先不講什么語(yǔ)法原理先根據(jù)效果強(qiáng)行模擬語(yǔ)法使用實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的第一步我們先用類 React系列 React系列 --- 簡(jiǎn)單模擬語(yǔ)法(一)React系列 --- Jsx, 合成事件與Refs(二)React系列 --- virtualdom diff算法實(shí)現(xiàn)分析...

    piglei 評(píng)論0 收藏0
  • [React Native Android 安利系列]ReactNative中的reactjs基礎(chǔ)

    摘要:個(gè)人感覺(jué)這與中的布局文件類似。其中的會(huì)被解析。中的標(biāo)簽,由基礎(chǔ)庫(kù)提供。認(rèn)為,我們的程序是一個(gè)狀態(tài)機(jī)。支持我們更改狀態(tài),從而引起視圖的變化。綁定事件是放在中的。事件名稱直接寫(xiě)為標(biāo)簽的屬性,其值則是對(duì)應(yīng)的事件處理函數(shù)。 這一系列課程說(shuō)了很多關(guān)于react-native的知識(shí),都是有關(guān)于樣式,底層,環(huán)境等知識(shí)的,現(xiàn)在我們來(lái)學(xué)習(xí)一下reactjs的基礎(chǔ)知識(shí)。我們的代碼,我們創(chuàng)建的組件的相關(guān)知識(shí)...

    EddieChan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<