99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

復(fù)合組件

2019-08-14 14:28 更新

目前為止,我們已經(jīng)學(xué)了如何用單個(gè)組件來(lái)展示數(shù)據(jù)和處理用戶輸入。下一步讓我們來(lái)體驗(yàn) React 最激動(dòng)人心的特性之一:可組合性(composability)。

動(dòng)機(jī):關(guān)注分離

通過(guò)復(fù)用那些接口定義良好的組件來(lái)開發(fā)新的模塊化組件,我們得到了與使用函數(shù)和類相似的好處。具體來(lái)說(shuō)就是能夠通過(guò)開發(fā)簡(jiǎn)單的組件把程序的不同關(guān)注面分離。如果為程序開發(fā)一套自定義的組件庫(kù),那么就能以最適合業(yè)務(wù)場(chǎng)景的方式來(lái)展示你的用戶界面。

組合實(shí)例

一起來(lái)使用 Facebook Graph API 開發(fā)顯示個(gè)人圖片和用戶名的簡(jiǎn)單 Avatar 組件吧。

var Avatar = React.createClass({
  render: function() {    return (
      <div>
        <ProfilePic username={this.props.username} />
        <ProfileLink username={this.props.username} />
      </div>
    );
  }
});var ProfilePic = React.createClass({
  render: function() {    return (
      <img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />
    );
  }
});var ProfileLink = React.createClass({
  render: function() {    return (
      <a href={'http://www.facebook.com/' + this.props.username}>
        {this.props.username}
      </a>
    );
  }
});

React.render(
  <Avatar username="pwh" />,
  document.getElementById('example')
);

從屬關(guān)系

上面例子中,Avatar 擁有 ProfilePic 和 ProfileLink 的實(shí)例。擁有者 就是給其它組件設(shè)置 props 的那個(gè)組件。更正式地說(shuō), 如果組件 Y 在render() 方法是創(chuàng)建了組件 X,那么 Y 就擁有 X。上面講過(guò),組件不能修改自身的 props - 它們總是與它們擁有者設(shè)置的保持一致。這是保持用戶界面一致性的關(guān)鍵性原則。

把從屬關(guān)系與父子關(guān)系加以區(qū)別至關(guān)重要。從屬關(guān)系是 React 特有的,而父子關(guān)系簡(jiǎn)單來(lái)講就是 DOM 里的標(biāo)簽的關(guān)系。在上一個(gè)例子中,Avatar 擁有div、ProfilePic 和 ProfileLink 實(shí)例,div 是 ProfilePic 和 ProfileLink 實(shí)例的父級(jí)(但不是擁有者)。

子級(jí)

實(shí)例化 React 組件時(shí),你可以在開始標(biāo)簽和結(jié)束標(biāo)簽之間引用在 React 組件或者 Javascript 表達(dá)式:

<Parent><Child /></Parent>

Parent 能通過(guò)專門的 this.props.children props 讀取子級(jí)。this.props.children 是一個(gè)不透明的數(shù)據(jù)結(jié)構(gòu): 通過(guò) React.Children 工具類來(lái)操作。

子級(jí)校正(Reconciliation)

校正就是每次 render 方法調(diào)用后 React 更新 DOM 的過(guò)程。 一般情況下,子級(jí)會(huì)根據(jù)它們被渲染的順序來(lái)做校正。例如,下面代碼描述了兩次渲染的過(guò)程:

// 第一次渲染<Card>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p></Card>// 第二次渲染<Card>
  <p>Paragraph 2</p></Card>

直觀來(lái)看,只是刪除了<p>Paragraph 1</p>。事實(shí)上,React 先更新第一個(gè)子級(jí)的內(nèi)容,然后刪除最后一個(gè)組件。React 是根據(jù)子級(jí)的順序來(lái)校正的。

子組件狀態(tài)管理

對(duì)于大多數(shù)組件,這沒(méi)什么大礙。但是,對(duì)于使用 this.state 來(lái)在多次渲染過(guò)程中里維持?jǐn)?shù)據(jù)的狀態(tài)化組件,這樣做潛在很多問(wèn)題。

多數(shù)情況下,可以通過(guò)隱藏組件而不是刪除它們來(lái)繞過(guò)這些問(wèn)題。

// 第一次渲染<Card>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p></Card>// 第二次渲染<Card>
  <p style={{'{{'}}display: 'none'}}>Paragraph 1</p>
  <p>Paragraph 2</p></Card>

動(dòng)態(tài)子級(jí)

如果子組件位置會(huì)改變(如在搜索結(jié)果中)或者有新組件添加到列表開頭(如在流中)情況會(huì)變得更加復(fù)雜。如果子級(jí)要在多個(gè)渲染階段保持自己的特征和狀態(tài),在這種情況下,你可以通過(guò)給子級(jí)設(shè)置惟一標(biāo)識(shí)的 key 來(lái)區(qū)分。

  render: function() {    var results = this.props.results;    return (
      <ol>
        {results.map(function(result) {          return <li key={result.id}>{result.text}</li>;
        })}
      </ol>
    );
  }

當(dāng) React 校正帶有 key 的子級(jí)時(shí),它會(huì)確保它們被重新排序(而不是破壞)或者刪除(而不是重用)。 務(wù)必 把 key 添加到子級(jí)數(shù)組里組件本身上,而不是每個(gè)子級(jí)內(nèi)部最外層 HTML 上:

// 錯(cuò)誤!var ListItemWrapper = React.createClass({
  render: function() {    return <li key={this.props.data.id}>{this.props.data.text}</li>;
  }
});var MyComponent = React.createClass({
  render: function() {    return (
      <ul>
        {this.props.results.map(function(result) {          return <ListItemWrapper data={result}/>;
        })}
      </ul>
    );
  }
});// 正確 :)var ListItemWrapper = React.createClass({
  render: function() {    return <li>{this.props.data.text}</li>;
  }
});var MyComponent = React.createClass({
  render: function() {    return (
      <ul>
        {this.props.results.map(function(result) {           return <ListItemWrapper key={result.id} data={result}/>;
        })}
      </ul>
    );
  }
});

也可以傳遞 object 來(lái)做有 key 的子級(jí)。object 的 key 會(huì)被當(dāng)作每個(gè)組件的 key。但是一定要牢記 JavaScript 并不總是保證屬性的順序會(huì)被保留。實(shí)際情況下瀏覽器一般會(huì)保留屬性的順序,除了 使用 32 位無(wú)符號(hào)數(shù)字做為 key 的屬性。數(shù)字型屬性會(huì)按大小排序并且排在其它屬性前面。一旦發(fā)生這種情況,React 渲染組件的順序就是混亂??赡茉?key 前面加一個(gè)字符串前綴來(lái)避免:

  render: function() {    var items = {};    this.props.results.forEach(function(result) {      // 如果 result.id 看起來(lái)是一個(gè)數(shù)字(比如短哈希),那么
      // 對(duì)象字面量的順序就得不到保證。這種情況下,需要添加前綴
      // 來(lái)確保 key 是字符串。
      items['result-' + result.id] = <li>{result.text}</li>;
    });    return (      <ol>
        {items}      </ol>
    );
  }

數(shù)據(jù)流

React 里,數(shù)據(jù)通過(guò)上面介紹過(guò)的 props 從擁有者流向歸屬者。這就是高效的單向數(shù)據(jù)綁定(one-way data binding):擁有者通過(guò)它的 props state 計(jì)算出一些值,并把這些值綁定到它們擁有的組件的 props 上。因?yàn)檫@個(gè)過(guò)程會(huì)遞歸地調(diào)用,所以數(shù)據(jù)變化會(huì)自動(dòng)在所有被使用的地方自動(dòng)反映出來(lái)。

性能提醒

你或許會(huì)擔(dān)心如果一個(gè)擁有者有大量子級(jí)時(shí),對(duì)于數(shù)據(jù)變化做出響應(yīng)非常耗費(fèi)性能。值得慶幸的是執(zhí)行 JavaScript 非常的快,而且 render() 方法一般比較簡(jiǎn)單,所以在大部分應(yīng)用里這樣做速度極快。此外,性能的瓶頸大多是因?yàn)?DOM 更新,而非 JS 執(zhí)行,而且 React 會(huì)通過(guò)批量更新和變化檢測(cè)來(lái)優(yōu)化性能。

但是,有時(shí)候需要做細(xì)粒度的性能控制。這種情況下,可以重寫 shouldComponentUpdate() 方法返回 false 來(lái)讓 React 跳過(guò)對(duì)子樹的處理。參考 React reference docs 了解更多。

注意:

如果在數(shù)據(jù)變化時(shí)讓 shouldComponentUpdate() 返回 false,React 就不能保證用戶界面同步。當(dāng)使用它的時(shí)候一定確保你清楚到底做了什么,并且只在遇到明顯性能問(wèn)題的時(shí)候才使用它。不要低估 JavaScript 的速度,DOM 操作通常才是慢的原因。


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)