国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

玩轉(zhuǎn) React(六)- 處理事件

Astrian / 1330人閱讀

摘要:綁定事件處理函數(shù)指向的四中方式以及他們的優(yōu)缺點(diǎn)。內(nèi)部自己實(shí)現(xiàn)了一套高效的事件機(jī)制,為了提高框架的性能,通過(guò)事件冒泡,只在節(jié)點(diǎn)上注冊(cè)原生的事件,內(nèi)部自己管理所有組件的事件處理函數(shù),以及事件的冒泡捕獲。

前面的文章介紹了 React 的 JSX 語(yǔ)法、組件的創(chuàng)建方式、組件的屬性、組件的內(nèi)部狀態(tài)以及組件的生命周期。另外,還順帶說(shuō)了各個(gè)知識(shí)點(diǎn)要重點(diǎn)注意的事情,以及我在項(xiàng)目實(shí)踐中的一些經(jīng)驗(yàn)。如果你覺(jué)得對(duì)自己有幫助,可以通過(guò) 玩轉(zhuǎn) React(一)- 前言 中的文章目錄進(jìn)行閱讀。

另外,為了方便大家更好地交流 React、分享前端開(kāi)發(fā)經(jīng)驗(yàn),我建了一個(gè)微信群,由于微信群二維碼有時(shí)間限制,你可以先加我好友(我的微信:leobaba88),驗(yàn)證信息 玩轉(zhuǎn) React,我會(huì)拉你入群,歡迎大家,下面是我的微信二維碼。

好的,言歸正傳,今天我們說(shuō)一下在 React 中是如何處理事件的。事件處理是前端開(kāi)發(fā)過(guò)程中非常重要的一部分,通過(guò)事件處理機(jī)制,我們的前端應(yīng)用可以響應(yīng)用戶(hù)的各種操作,從而實(shí)現(xiàn)一個(gè)富交互的前端應(yīng)用。

內(nèi)容摘要

如何為 React 的內(nèi)置組件設(shè)置事件處理函數(shù)。

React 事件對(duì)象與瀏覽器原生 DOM 事件對(duì)象的區(qū)別。

默認(rèn)情況下不能以異步的方式使用事件對(duì)象,如在 setTimeout 中。

不要在組件中使用 addEventListener 注冊(cè)事件處理函數(shù),有坑。

綁定事件處理函數(shù) this 指向的四中方式以及他們的優(yōu)缺點(diǎn)。

React 內(nèi)置組件的事件處理

我所說(shuō)的 React 內(nèi)置組件是指 React 中已經(jīng)定義好的,可以直接使用的如 div、button、input 等與原生 HTML 標(biāo)簽對(duì)應(yīng)的組件。

我們先回顧一下瀏覽器原生 DOM 上注冊(cè)事件的方式。

第一種方式


    Click me.

這是一種古老的方式,在 DOM level 1 規(guī)范中的事件注冊(cè)方式,現(xiàn)在已經(jīng)很少使用了。

這種方式,用來(lái)注冊(cè)事件的 HTML 屬性的值是一個(gè)字符串,是一段需要執(zhí)行的 JavaScript 代碼。

可以通過(guò) return false; 來(lái)阻止當(dāng)前 HMTL 元素的默認(rèn)行為,如 a 標(biāo)簽的頁(yè)面跳轉(zhuǎn)。

關(guān)于 DOM 規(guī)范的級(jí)別可以參考:DOM Levels

第二種方式:


    Click me.


這是 DOM level 2 規(guī)范中引入的事件注冊(cè)方式,目前各瀏覽器也支持的很好,用得是最多的,就是寫(xiě)起來(lái)有點(diǎn)啰嗦哈。

在 React 中,事件注冊(cè)與方式一非常類(lèi)似,不過(guò)有如下幾點(diǎn)不同:

屬性名稱(chēng)采用駝峰式(如:onClick,onKeyDown),而不是全小寫(xiě)字母。

屬性值接受一個(gè)函數(shù),而不是字符串。

return false; 不會(huì)阻止組件的默認(rèn)行為,需要調(diào)用 e.preventDefault();

如下所示:

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log("The link was clicked.");
  }

  return (
    
      Click me
    
  );
}

這是一個(gè)以函數(shù)方式定義的組件,組件渲染一個(gè) a 元素,設(shè)置l鏈接的點(diǎn)擊事件,通過(guò)事件處理函數(shù)接收到的事件對(duì)象(e),阻止了鏈接的默認(rèn)行為,并打印 "The link was clicked." 到控制臺(tái)上。設(shè)置 React 內(nèi)置組件的事件處理函數(shù)是不是非常簡(jiǎn)單。

React 事件對(duì)象 VS 原生的 DOM 事件對(duì)象

React 中的事件對(duì)象稱(chēng)之為 SyntheticEvent(合成對(duì)象),它是依據(jù) DOM Level 3 的事件規(guī)范實(shí)現(xiàn)的,這樣做最大的好處是可以屏蔽瀏覽器的差異,各種廠商的瀏覽器對(duì)規(guī)范的實(shí)現(xiàn)程度是不一樣的,如果直接使用原生 DOM 事件對(duì)象的話,有些情況下你需要考慮瀏覽器的兼容性。而 React 通過(guò) SyntheticEvent 已經(jīng)把這些瑣事幫你搞定了,在任何 React 支持的瀏覽器下,事件對(duì)象都有一致的接口。

React 中所有的事件處理函數(shù)都會(huì)接收到一個(gè) SyntheticEvent 的實(shí)例 e 作為參數(shù),如果在某些特殊的場(chǎng)景中,你需要用到原生的 DOM 事件對(duì)象,可以通過(guò) e.nativeEvent 來(lái)獲取。

不要在異步過(guò)程中使用 React 事件對(duì)象

需要說(shuō)明的是,出于性能的考慮,React 并不是為每一個(gè)事件處理函數(shù)生成一個(gè)全新的事件對(duì)象,事件對(duì)象會(huì)被復(fù)用,當(dāng)事件處理函數(shù)被執(zhí)行以后,事件對(duì)象的所有屬性會(huì)被設(shè)置為 null,所以在事件處理函數(shù)中,你不能以異步的方式使用 React 的事件對(duì)象,因?yàn)槟菚r(shí)候事件對(duì)象的所有屬性都是 null 了,或者已經(jīng)不是你關(guān)心的那個(gè)事件了。

盡量不要使用 addEventListener

這里稍微深入一下,不然我怕有的同學(xué)會(huì)踩坑。React 內(nèi)部自己實(shí)現(xiàn)了一套高效的事件機(jī)制,為了提高框架的性能,React 通過(guò) DOM 事件冒泡,只在 document 節(jié)點(diǎn)上注冊(cè)原生的 DOM 事件,React 內(nèi)部自己管理所有組件的事件處理函數(shù),以及事件的冒泡、捕獲。

所以說(shuō),如果你通過(guò) addEventListener 注冊(cè)了某個(gè) DOM 節(jié)點(diǎn)的某事件處理函數(shù),并且通過(guò) e.stopPropagation(); 阻斷了事件的冒泡或者捕獲,那么該節(jié)點(diǎn)下的所有節(jié)點(diǎn)上,同類(lèi)型的 React 事件處理函數(shù)都會(huì)失效。

如下示例,雖然設(shè)置的鏈接的點(diǎn)擊事件,但是它卻執(zhí)行不了。

class CounterLink extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
    this.handleClick = this.handleClick.bind(this);
  }
  componentDidMount() {
    document.querySelector(".my-link").addEventListener("click", (e) => {
      console.info("raw click");
      e.stopPropagation();
    })
  }
  handleClick(e) {
    e.preventDefault();
    console.info("react click");
    this.setState({ count: this.state.count + 1 });
  }
  render() {
    return (
      
    )
  }
}
ReactDOM.render(, document.querySelector("#root"));

https://codepen.io/Sarike/pen...

如何綁定事件處理函數(shù)的 this

在以類(lèi)繼承的方式定義的組件中,為了能方便地調(diào)用當(dāng)前組件的其他成員方法或?qū)傩裕ㄈ纾簍his.state),通常需要將事件處理函數(shù)運(yùn)行時(shí)的 this 指向當(dāng)前組件實(shí)例。

如下面的示例:

class Link extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
  }
  handleClick(e) {
    e.preventDefault();
    this.setState({ count: this.state.count + 1 })
  }
  render() {
    return Clicked me {this.state.count} times.    
  }

}

ReactDOM.render(, document.querySelector("#root"))

當(dāng)點(diǎn)擊鏈接時(shí),控制臺(tái)會(huì)報(bào)錯(cuò):Uncaught TypeError: Cannot read property "setState" of undefined,就是因?yàn)闆](méi)有將 handleClick 運(yùn)行時(shí)的 this 綁定到當(dāng)前組件。

綁定事件處理函數(shù)的 this 到當(dāng)前組件,有如下幾種方式。

第一種方式,通過(guò) bind 方法,原地綁定事件處理函數(shù)的 this 指向,如下所示:


    Clicked me {this.state.count} times.

這種方式的優(yōu)點(diǎn)是書(shū)寫(xiě)起來(lái)相對(duì)簡(jiǎn)單,但是每次渲染都會(huì)執(zhí)行 bind 方法生成一個(gè)新的函數(shù),會(huì)有額外的開(kāi)銷(xiāo),由于事件處理函數(shù)是作為屬性傳遞的,所以從而導(dǎo)致子組件進(jìn)行重新渲染,顯然這不是一種好的方式。

第二種方式,通過(guò)一個(gè)箭頭函數(shù)將真實(shí)的事件處理函數(shù)包裝一下,如下所示:

 this.handleClick(e)}>
    Clicked me {this.state.count} times.

這種方式書(shū)寫(xiě)起來(lái)也不算麻煩,不過(guò)也沒(méi)有解決第一種方式面臨的性能開(kāi)銷(xiāo)和重新渲染的問(wèn)題。但是這種方式的一個(gè)好處是能清晰描述事件處理函數(shù)接收的參數(shù)列表(這一點(diǎn)可能因人而異,個(gè)人觀點(diǎn)覺(jué)得這是一個(gè)優(yōu)點(diǎn))。

第三種方式,在 constructor 中預(yù)先將所有的事件處理函數(shù)通過(guò) bind 方法進(jìn)行綁定。如下所示:

class Link extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
    
    // 重點(diǎn)在這里
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(e) {
    e.preventDefault();
    this.setState({ count: this.state.count + 1 })
  }
  render() {
    return Clicked me {this.state.count} times.    
  }
}

ReactDOM.render(, document.querySelector("#root"))

這種方式能解決前兩種方式面臨的額外開(kāi)銷(xiāo)和重新渲染的問(wèn)題,但是寫(xiě)起來(lái)略微有點(diǎn)復(fù)雜,因?yàn)橐粋€(gè)事件處理函數(shù)要分別在三個(gè)不同的地方進(jìn)行定義、綁定 this 和使用。

第四種方式,使用類(lèi)的成員字段定義語(yǔ)法,如下所示:

class Link extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
  }
  handleClick = e => {
    e.preventDefault();
    this.setState({ count: this.state.count + 1 })
  }
  render() {
    return Clicked me {this.state.count} times.    
  }
}
ReactDOM.render(, document.querySelector("#root"))

這種方式解決了上面三種方式面臨的性能開(kāi)銷(xiāo)、重新渲染以及書(shū)寫(xiě)麻煩的問(wèn)題。唯一的問(wèn)題就是這種語(yǔ)法目前處于 Stage 3,還未納入到正式的 ES 規(guī)范中。參考:https://github.com/tc39/propo...

不過(guò)這也沒(méi)太大關(guān)系。

總結(jié)

本文的內(nèi)容并不多,可能說(shuō)的有點(diǎn)啰嗦。簡(jiǎn)單總結(jié)一下,React 中通過(guò)設(shè)置組件的 事件屬性 來(lái)注冊(cè)事件,React 內(nèi)部自己實(shí)現(xiàn)了一套包含冒泡、捕獲邏輯在內(nèi)的事件機(jī)制,所以盡量不要使用 addEventListener,除非你知道自己在干什么。有四種為事件處理函數(shù)綁定 this 的方法,推薦使用類(lèi)屬性定義的方式來(lái)定義處理函數(shù),如果你不太在意哪一點(diǎn)性能開(kāi)銷(xiāo)的話,可以使用箭頭函數(shù)包裝真實(shí)事件回調(diào)的方式。另外,事件對(duì)象在 React 中是被復(fù)用的,事件回調(diào)被執(zhí)行以后,事件對(duì)象的所有屬性會(huì)被重置為 null,所以不要在異步的過(guò)程中使用事件對(duì)象。

好了,有什么疑問(wèn)可以加微信群交流,我的微信號(hào):leobaba88,驗(yàn)證信息:玩轉(zhuǎn) React。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/89549.html

相關(guān)文章

  • 玩轉(zhuǎn) React(一)- 前言

    摘要:本人計(jì)劃編寫(xiě)一個(gè)針對(duì)中初級(jí)前端開(kāi)發(fā)者學(xué)習(xí)的系列教程玩轉(zhuǎn)。使用的原因是新的語(yǔ)言規(guī)范開(kāi)發(fā)效率更高代碼更優(yōu)雅,尤其是基于開(kāi)發(fā)的項(xiàng)目。其次也是目前特別流行的一個(gè)前端框架,截止目前,上有將近萬(wàn),國(guó)內(nèi)一二線互聯(lián)網(wǎng)公司都有深度依賴(lài)開(kāi)發(fā)的項(xiàng)目。 本人計(jì)劃編寫(xiě)一個(gè)針對(duì)中初級(jí)前端開(kāi)發(fā)者學(xué)習(xí) React 的系列教程 - 《玩轉(zhuǎn) React》。 文章更新頻率:每周 1 ~ 2 篇。 目錄 玩轉(zhuǎn) React(...

    waltr 評(píng)論0 收藏0
  • 玩轉(zhuǎn) React(七)- 組件之間的數(shù)據(jù)共享

    摘要:函數(shù)屬性或者說(shuō)事件在組件之間通信過(guò)程中是必不可少的,但是切莫讓它影響了大家對(duì)單向數(shù)據(jù)流這一概念的理解。這應(yīng)該屬于一種的使用方式,而且這樣做有悖單向數(shù)據(jù)流原則。 上一篇文章 玩轉(zhuǎn) React(六)- 處理事件 介紹了在 React 中如何處理用戶(hù)事件,以及 React 事件機(jī)制與原生 DOM 事件的差異和注意的問(wèn)題,同時(shí)也介紹了事件處理函數(shù)中 this 的指向問(wèn)題以及處理的幾種方式及其優(yōu)...

    Gu_Yan 評(píng)論0 收藏0
  • 玩轉(zhuǎn) React(五)- 組件的內(nèi)部狀態(tài)和生命周期

    摘要:另外本文中會(huì)介紹一個(gè)通過(guò)類(lèi)繼承方式定義的組件的生命周期,以及在各個(gè)生命周期函數(shù)中能做什么,不能或盡量不要做什么。各個(gè)生命周期函數(shù)介紹及使用經(jīng)驗(yàn)。獲取組件的初始內(nèi)部狀態(tài)在中。該聲明周期函數(shù)可能在兩種情況下被調(diào)用組件接收到了新的屬性。 文章標(biāo)題總算是可以正常一點(diǎn)了…… 通過(guò)之前的文章我們已經(jīng)知道:在 React 體系中所謂的 在 JavaScript 中編寫(xiě) HTML 代碼 指的是 Rea...

    Rocture 評(píng)論0 收藏0
  • 玩轉(zhuǎn) React(五)- 組件的內(nèi)部狀態(tài)和生命周期

    摘要:另外本文中會(huì)介紹一個(gè)通過(guò)類(lèi)繼承方式定義的組件的生命周期,以及在各個(gè)生命周期函數(shù)中能做什么,不能或盡量不要做什么。各個(gè)生命周期函數(shù)介紹及使用經(jīng)驗(yàn)。獲取組件的初始內(nèi)部狀態(tài)在中。該聲明周期函數(shù)可能在兩種情況下被調(diào)用組件接收到了新的屬性。 文章標(biāo)題總算是可以正常一點(diǎn)了…… 通過(guò)之前的文章我們已經(jīng)知道:在 React 體系中所謂的 在 JavaScript 中編寫(xiě) HTML 代碼 指的是 Rea...

    ASCH 評(píng)論0 收藏0
  • React源碼剖析系列 - 玩轉(zhuǎn) React Transition

    摘要:后面將會(huì)仔細(xì)分析的源碼實(shí)現(xiàn)。更新完成后,對(duì)中的每個(gè)元素執(zhí)行動(dòng)畫(huà)的邏輯,對(duì)中的每個(gè)元素執(zhí)行動(dòng)畫(huà)的邏輯。事實(shí)上,原因很簡(jiǎn)單,事件在某些情況是不會(huì)被觸發(fā)??偨Y(jié)動(dòng)畫(huà)是組件初次后,才會(huì)被添加到的所有子元素上。參考資料官方文檔事件 過(guò)去一年,React 給整個(gè)前端界帶來(lái)了一種新的開(kāi)發(fā)方式,我們拋棄了無(wú)所不能的 DOM 操作。對(duì)于 React 實(shí)現(xiàn)動(dòng)畫(huà)這個(gè)命題,DOM 操作已經(jīng)是一條死路,而 CSS...

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

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

0條評(píng)論

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