瀏覽器中的工作原理

2019-08-14 14:28 更新

React提供了強大的抽象,讓你在大多數(shù)應用場景中不再直接操作DOM,但是有時你需要簡單地調(diào)用底層的API,或者借助于第三方庫或已有的代碼。

虛擬DOM

React是很快的,因為它從不直接操作DOM。React在內(nèi)存中維護一個快速響應的DOM描述。render()方法返回一個DOM的描述,React能夠利用內(nèi)存中的描述來快速地計算出差異,然后更新瀏覽器中的DOM。

另外,React實現(xiàn)了一個完備的虛擬事件系統(tǒng),盡管各個瀏覽器都有自己的怪異行為,React確保所有事件對象都符合W3C規(guī)范,并且持續(xù)冒泡,用一種高性能的方式跨瀏覽器(and everything bubbles consistently and in a performant way cross-browser)。你甚至可以在IE8中使用一些HTML5的事件!

大多數(shù)時候你應該呆在React的“虛擬瀏覽器”世界里面,因為它性能更加好,并且容易思考。但是,有時你簡單地需要調(diào)用底層的API,或許借助于第三方的類似于jQuery插件這種庫。React為你提供了直接使用底層DOM API的途徑。

Refs和getDOMNode()

為了和瀏覽器交互,你將需要對DOM節(jié)點的引用。每一個掛載的React組件有一個getDOMNode()方法,你可以調(diào)用這個方法來獲取對該節(jié)點的引用。

注意:

getDOMNode()僅在掛載的組件上有效(也就是說,組件已經(jīng)被放進了DOM中)。如果你嘗試在一個未被掛載的組件上調(diào)用這個函數(shù)(例如在創(chuàng)建組件的render()函數(shù)中調(diào)用getDOMNode()),將會拋出異常。

為了獲取一個到React組件的引用,你可以使用this來得到當前的React組件,或者你可以使用refs來指向一個你擁有的組件。它們像這樣工作:

var MyComponent = React.createClass({
  handleClick: function() {    // Explicitly focus the text input using the raw DOM API.
    this.refs.myTextInput.getDOMNode().focus();
  },
  render: function() {    // The ref attribute adds a reference to the component to
    // this.refs when the component is mounted.
    return (
      <div>
        <input type="text" ref="myTextInput" />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.handleClick}
        />
      </div>
    );
  }
});

React.render(
  <MyComponent />,
  document.getElementById('example')
);

更多關(guān)于 Refs

為了學習更多有關(guān)Refs的內(nèi)容,包括如何有效地使用它們,參考我們的更多關(guān)于Refs文檔。

組件生命周期

組件的生命周期包含三個主要部分:

  • 掛載: 組件被插入到DOM中。

  • 更新: 組件被重新渲染,查明DOM是否應該刷新。

  • 移除: 組件從DOM中移除。

React提供生命周期方法,你可以在這些方法中放入自己的代碼。我們提供will方法,會在某些行為發(fā)生之前調(diào)用,和did方法,會在某些行為發(fā)生之后調(diào)用。

掛載

  • getInitialState(): object在組件被掛載之前調(diào)用。狀態(tài)化的組件應該實現(xiàn)這個方法,返回初始的state數(shù)據(jù)。

  • componentWillMount()在掛載發(fā)生之前立即被調(diào)用。

  • componentDidMount()在掛載結(jié)束之后馬上被調(diào)用。需要DOM節(jié)點的初始化操作應該放在這里。

更新

  • componentWillReceiveProps(object nextProps)當一個掛載的組件接收到新的props的時候被調(diào)用。該方法應該用于比較this.propsnextProps,然后使用this.setState()來改變state。

  • shouldComponentUpdate(object nextProps, object nextState): boolean當組件做出是否要更新DOM的決定的時候被調(diào)用。實現(xiàn)該函數(shù),優(yōu)化this.propsnextProps,以及this.statenextState的比較,如果不需要React更新DOM,則返回false。

  • componentWillUpdate(object nextProps, object nextState)在更新發(fā)生之前被調(diào)用。你可以在這里調(diào)用this.setState()。

  • componentDidUpdate(object prevProps, object prevState)在更新發(fā)生之后調(diào)用。

移除

  • componentWillUnmount()在組件移除和銷毀之前被調(diào)用。清理工作應該放在這里。

掛載的方法(Mounted Methods)

_掛載的_復合組件也支持如下方法:

  • getDOMNode(): DOMElement可以在任何掛載的組件上面調(diào)用,用于獲取一個指向它的渲染DOM節(jié)點的引用。

  • forceUpdate()當你知道一些很深的組件state已經(jīng)改變了的時候,可以在該組件上面調(diào)用,而不是使用this.setState()

跨瀏覽器支持和兼容代碼(Browser Support and Polyfills)

在 Facebook,我們支持老版本的瀏覽器,包括 IE8。我們已經(jīng)擁有適當?shù)?polyfills 很長一段時間了,能夠允許我們寫有遠見的 JS。這意味著在我們的代碼庫中沒有黑客,我們?nèi)匀豢梢云诖覀兊拇a“工作”。例如,不用寫 +new Date(),我們可以只寫 Date.now()。由于開源的 React 和我們內(nèi)部使用的是一樣的,所以我們采取了使用超前思維 JS 的這種理念。

除了那種理念,我們也確立了我們的立場,作為一個 JS 庫的作者,不應該把 polyfills 作為庫的一部分 shipping。如果每個庫都這么做,很有可能你會多次發(fā)送相同的 polyfill,這可能相當于一部分無用代碼。如果你的產(chǎn)品需要支持老版本的瀏覽器,很有可能你已經(jīng)在使用類似 es5-shim 的東西了。

為了支持老版本瀏覽器所需的 polyfill

來自 kriskowal's es5-shim  es5-shim.js 提供了 React 所需的如下方法:

  • Array.isArray

  • Array.prototype.every

  • Array.prototype.forEach

  • Array.prototype.indexOf

  • Array.prototype.map

  • Date.now

  • Function.prototype.bind

  • Object.keys

  • String.prototype.split

  • String.prototype.trim

es5-sham.js,同樣來自 kriskowal's es5-shim,提供了 React 所需的如下方法:

  • Object.create

  • Object.freeze

React 的 unminified 構(gòu)建需要來自 paulmillr's console-polyfill 的如下方法:

  • console.*

當使用 IE8 中的 HTML5 元素時,包括 <section>,<article>, <nav><header> <footer>,包含 html5shiv 或類似的一個腳本也是必須的。

跨瀏覽器問題

雖然 React 非常擅長抽象瀏覽器的差異,但是一些瀏覽器是有限制的或呈現(xiàn)出怪異的行為,對于這種行為我們不能找到解決方案。

IE8 的 onScroll 事件

在 IE8 中,onScroll 事件并不 buddle,并且 IE8 沒有一個 API 定義處理程序來捕獲一個事件的階段,這意味著 React 沒有辦法監(jiān)聽這些事件。目前在 IE8 中,事件處理程序被忽略了。

更多信息請看 onScroll 在 IE8 中不起作用的 GitHub 問題。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號