亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

React編程思想

ckllj / 454人閱讀

摘要:的單向數(shù)據(jù)流也稱為單向綁定使所有的事務(wù)更加模塊化也更加快速。第五步添加反向數(shù)據(jù)流到目前為止,我們已經(jīng)構(gòu)建了一個(gè)應(yīng)用程序,可以根據(jù)和正確地呈現(xiàn)在層次結(jié)構(gòu)中。傳遞的回調(diào)將調(diào)用,并且應(yīng)用程序?qū)⒈桓隆?/p>

本文是對(duì)React官網(wǎng)《Thinking in React》一文的翻譯,通過(guò)這篇文章,React團(tuán)隊(duì)向開(kāi)發(fā)者們介紹了應(yīng)該如果去構(gòu)思一個(gè)web應(yīng)用,為今后使用React進(jìn)行web app的構(gòu)建,打下基礎(chǔ)。 以下是正文。

在我們團(tuán)隊(duì)看來(lái),React是使用JavaScript構(gòu)建大型、快速的Web apps的首選方式。它已經(jīng)在Facebook和Instagram項(xiàng)目中,表現(xiàn)出了非常好的可擴(kuò)展性。

能夠按照構(gòu)建的方式來(lái)思考web app的實(shí)現(xiàn),是React眾多優(yōu)點(diǎn)之一。在這篇文章中,我們將引導(dǎo)你進(jìn)行使用React構(gòu)建可搜索產(chǎn)品數(shù)據(jù)表的思考過(guò)程。

從設(shè)計(jì)稿開(kāi)始

想象一下,我們已經(jīng)有了一個(gè)JSON API和來(lái)自設(shè)計(jì)師的設(shè)計(jì)稿。如下圖所示:

JSON API返回的數(shù)據(jù)如下所示:

[
  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];
第一步:將UI分解為組件并分析層級(jí)結(jié)構(gòu)

我們要做的第一件事就是給設(shè)計(jì)稿中的每個(gè)組件(和子組件)畫(huà)框,并給它們起名字。如果你正在和一個(gè)設(shè)計(jì)師合作,他可能已經(jīng)幫你完成了這一步。他的Photoshop圖層名稱可能最終會(huì)成為你的React組件名稱!

但我們?cè)趺粗雷约旱慕M件應(yīng)該是什么?只需要使用一些通用的技巧來(lái)決定是否應(yīng)該創(chuàng)建一個(gè)新的函數(shù)或?qū)ο?。其中一個(gè)技巧叫做:單一責(zé)任原則。就是說(shuō),在理想情況下,一個(gè)組件應(yīng)該只用來(lái)完成一件事。若非如此,則應(yīng)該考慮將其分解成更小的子組件。

我們經(jīng)常會(huì)向用戶展示JSON數(shù)據(jù)模型,那么你應(yīng)該會(huì)發(fā)現(xiàn),如果模型構(gòu)建正確,那么你的UI(以及組件結(jié)構(gòu))應(yīng)該能夠很好地映射數(shù)據(jù)模型。這是因?yàn)閁I和數(shù)據(jù)模型傾向于遵循相同的信息架構(gòu),這意味著將UI分解為組件的工作通常是微不足道的?,F(xiàn)在我們把它分解成映射數(shù)據(jù)模型的組件如下:

現(xiàn)在我們的示例應(yīng)用中有了五個(gè)組件,而且我們將每個(gè)組件代表的數(shù)據(jù)用斜體表示如下:

FilterableProductTable (橘黃色):包含整個(gè)示例的組件

SearchBar (藍(lán)色):接收所有的用戶輸入

ProductTable (綠色):根據(jù)用戶輸入顯示和過(guò)濾數(shù)據(jù)集

ProductCategoryRow (綠寶石色):顯示分類頭

ProductRow (紅色):每行顯示一條商品數(shù)據(jù)

細(xì)心的你會(huì)發(fā)現(xiàn),在ProductTable中,表頭(包含名稱價(jià)格標(biāo)簽)不是一個(gè)組件。這是一個(gè)偏好的問(wèn)題,有兩個(gè)方面的論點(diǎn)。在這個(gè)例子中,我們將其作為ProductTable組件的一部分,因?yàn)樗?b>ProductTable負(fù)責(zé)渲染的數(shù)據(jù)集的一部分。但是,如果這個(gè)頭部變得很復(fù)雜(比如我們要支持排序),那么將其設(shè)置為ProductTableHeader這樣的組件肯定會(huì)更好一些。

現(xiàn)在我們已經(jīng)確定了設(shè)計(jì)稿中的組件,下一步我們要給這些組件安排層次結(jié)構(gòu)。這其實(shí)很容易:出現(xiàn)在一個(gè)組件中的組件應(yīng)該在層次結(jié)構(gòu)中顯示為一個(gè)子組件:

FilterableProductTable

SearchBar

ProductTable

ProductCategoryRow

ProductRow

第二步:用React構(gòu)建一個(gè)靜態(tài)版本
class ProductCategoryRow extends React.Component {
  render() {
    const category = this.props.category;
    return (
      
        
          {category}
        
      
    );
  }
}

class ProductRow extends React.Component {
  render() {
    const product = this.props.product;
    const name = product.stocked ?
      product.name :
      
        {product.name}
      ;

    return (
      
        {name}
        {product.price}
      
    );
  }
}

class ProductTable extends React.Component {
  render() {
    const rows = [];
    let lastCategory = null;
    
    this.props.products.forEach((product) => {
      if (product.category !== lastCategory) {
        rows.push(
          
        );
      }
      rows.push(
        
      );
      lastCategory = product.category;
    });

    return (
      {rows}
Name Price
); } } class SearchBar extends React.Component { render() { return (

{" "} Only show products in stock

); } } class FilterableProductTable extends React.Component { render() { return (
); } } const PRODUCTS = [ {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"}, {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"}, {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"}, {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"}, {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"}, {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"} ]; ReactDOM.render( , document.getElementById("container") );

現(xiàn)在我們已經(jīng)有了組件層次結(jié)構(gòu),接下來(lái)可以實(shí)現(xiàn)應(yīng)用程序了。最初的方案是構(gòu)建一個(gè)使用數(shù)據(jù)模型渲染UI但不具有交互性的版本。最好將靜態(tài)版本和添加交互性進(jìn)行解耦,因?yàn)闃?gòu)建一個(gè)靜態(tài)的版本需要大量的輸入?yún)s不需要思考,而增加交互性需要大量的思考而不需要很多輸入。我們一會(huì)兒會(huì)知道為什么。

要構(gòu)建渲染數(shù)據(jù)模型的靜態(tài)版本,需要構(gòu)建可復(fù)用其他組件并使用props傳遞數(shù)據(jù)的組件。props是一種將數(shù)據(jù)從父組件傳遞給子組件的方式。如果你熟悉state的概念,請(qǐng)不要使用state來(lái)構(gòu)建這個(gè)靜態(tài)版本。state只為實(shí)現(xiàn)交互性而保留,即隨時(shí)間變化的數(shù)據(jù)。由于這是應(yīng)用程序的靜態(tài)版本,所以暫時(shí)不需要它。

你的構(gòu)建過(guò)程可以自上而下或自下而上。也就是說(shuō),你可以從構(gòu)建層次較高的組件(即FilterableProductTable)開(kāi)始或較低的組件(ProductRow開(kāi)始)。在簡(jiǎn)單的例子中,自上而下通常比較容易,而在大型項(xiàng)目中,自下而上更容易而且更易于編寫(xiě)測(cè)試用例。

在這一步的最后,你會(huì)有一個(gè)可重用組件的庫(kù)來(lái)渲染你的數(shù)據(jù)模型。這些組件只會(huì)有render()方法,因?yàn)檫@是你的應(yīng)用程序的靜態(tài)版本。層次結(jié)構(gòu)頂部的組件(FilterableProductTable)將把你的數(shù)據(jù)模型作為一個(gè)prop。如果你對(duì)基礎(chǔ)數(shù)據(jù)模型進(jìn)行更改并再次調(diào)用ReactDOM.render(),則UI將會(huì)更新。這就很容易看到用戶界面是如何更新以及在哪里進(jìn)行更改了,因?yàn)闆](méi)有任何復(fù)雜的事情發(fā)生。 React的單向數(shù)據(jù)流(也稱為單向綁定)使所有的事務(wù)更加模塊化也更加快速。

第三步:確定UI狀態(tài)的最?。ǖ暾┍硎拘问?/b>

為了使你的UI具有交互性,需要能夠觸發(fā)對(duì)基礎(chǔ)數(shù)據(jù)模型的更改。 React使用state讓這一切變得簡(jiǎn)單。要正確構(gòu)建應(yīng)用程序,首先需要考慮應(yīng)用程序需要的最小可變狀態(tài)集。這里的關(guān)鍵是:不要重復(fù)自己。找出應(yīng)用程序需要的狀態(tài)的絕對(duì)最小表示,并計(jì)算需要的其他所有內(nèi)容。例如,如果你正在創(chuàng)建一個(gè)TODO列表,只需要保存一個(gè)TODO項(xiàng)目的數(shù)組;不要為計(jì)數(shù)保留一個(gè)多帶帶的狀態(tài)變量。相反,當(dāng)你要渲染TODO數(shù)量時(shí),只需取TODO項(xiàng)目數(shù)組的長(zhǎng)度即可。

考慮我們示例應(yīng)用程序中的所有數(shù)據(jù)。我們有:

產(chǎn)品的原始列表

用戶輸入的搜索文本

復(fù)選框的值

過(guò)濾的產(chǎn)品列表

我們來(lái)看看每一個(gè)是哪一個(gè)state。這里有關(guān)于每條數(shù)據(jù)的三個(gè)問(wèn)題:

是通過(guò)props從父組件傳入的嗎?如果是,那可能不是state。

它是否保持不變?如果是,那可能不是state。

你能基于組件中的任何其他state或props來(lái)計(jì)算它嗎?如果是,那不是state。

原來(lái)的產(chǎn)品清單是作為props傳入的,所以這不是state。搜索文本和復(fù)選框似乎是state,因?yàn)樗鼈冸S著時(shí)間而改變,不能從任何東西計(jì)算。最后,產(chǎn)品的過(guò)濾列表不是state,因?yàn)樗梢酝ㄟ^(guò)將產(chǎn)品的原始列表與復(fù)選框的搜索文本和值組合來(lái)計(jì)算得到。

所以最后,我們的states是:

用戶輸入的搜索文本

復(fù)選框的值

第四步: 確定你的state需要放置在什么地方
class ProductCategoryRow extends React.Component {
  render() {
    const category = this.props.category;
    return (
      
        
          {category}
        
      
    );
  }
}

class ProductRow extends React.Component {
  render() {
    const product = this.props.product;
    const name = product.stocked ?
      product.name :
      
        {product.name}
      ;

    return (
      
        {name}
        {product.price}
      
    );
  }
}

class ProductTable extends React.Component {
  render() {
    const filterText = this.props.filterText;
    const inStockOnly = this.props.inStockOnly;

    const rows = [];
    let lastCategory = null;

    this.props.products.forEach((product) => {
      if (product.name.indexOf(filterText) === -1) {
        return;
      }
      if (inStockOnly && !product.stocked) {
        return;
      }
      if (product.category !== lastCategory) {
        rows.push(
          
        );
      }
      rows.push(
        
      );
      lastCategory = product.category;
    });

    return (
      {rows}
Name Price
); } } class SearchBar extends React.Component { render() { const filterText = this.props.filterText; const inStockOnly = this.props.inStockOnly; return (

{" "} Only show products in stock

); } } class FilterableProductTable extends React.Component { constructor(props) { super(props); this.state = { filterText: "", inStockOnly: false }; } render() { return (
); } } const PRODUCTS = [ {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"}, {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"}, {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"}, {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"}, {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"}, {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"} ]; ReactDOM.render( , document.getElementById("container") );

現(xiàn)在我們已經(jīng)確定了最小的一組應(yīng)用程序state。接下來(lái),我們需要確定哪個(gè)組件會(huì)改變或擁有這個(gè)state。

請(qǐng)記?。簲?shù)據(jù)在React的組件層次結(jié)構(gòu)中是單向流動(dòng)的。它可能不清楚哪個(gè)組件應(yīng)該擁有什么狀態(tài)。這通常是新手理解的最具挑戰(zhàn)性的部分,所以請(qǐng)按照以下步驟解決:

對(duì)于你的應(yīng)用程序中的每一個(gè)state:

確定基于該state渲染某些內(nèi)容的每個(gè)組件。

找到一個(gè)共同的擁有者組件(一個(gè)在所有需要該state的層次結(jié)構(gòu)組件之上的組件)。

無(wú)論是共同所有者,還是高層次的其他組成部分,都應(yīng)該擁有這個(gè)state。

如果你無(wú)法找到一個(gè)有意義的組件,那么只好創(chuàng)建一個(gè)新的組件來(lái)保存state,并將其添加到公共所有者組件上方的層次結(jié)構(gòu)中的某個(gè)位置。

讓我們來(lái)看看我們的應(yīng)用程序的這個(gè)策略:

ProductTable需要根據(jù)狀態(tài)過(guò)濾產(chǎn)品列表,而SearchBar需要顯示搜索文本和檢查狀態(tài)。

通用所有者組件是FilterableProductTable。

從概念上講,過(guò)濾器文本和選中的值存在于FilterableProductTable中是有意義的

酷,所以我們已經(jīng)決定,我們的state存活在FilterableProductTable中。首先,將一個(gè)實(shí)例屬性this.state = {filterText:"",inStockOnly:false}添加到FilterableProductTable的構(gòu)造函數(shù)中,以反映應(yīng)用程序的初始狀態(tài)。然后,將filterTextinStockOnly作為prop傳遞給ProductTableSearchBar。最后,使用這些props來(lái)篩選ProductTable中的行,并在SearchBar中設(shè)置表單域的值。

你可以看到你的應(yīng)用程序的行為了:設(shè)置filterText為“ball”,并刷新你的應(yīng)用程序。你將看到數(shù)據(jù)表已正確更新。

第五步:添加反向數(shù)據(jù)流
class ProductCategoryRow extends React.Component {
  render() {
    const category = this.props.category;
    return (
      
        
          {category}
        
      
    );
  }
}

class ProductRow extends React.Component {
  render() {
    const product = this.props.product;
    const name = product.stocked ?
      product.name :
      
        {product.name}
      ;

    return (
      
        {name}
        {product.price}
      
    );
  }
}

class ProductTable extends React.Component {
  render() {
    const filterText = this.props.filterText;
    const inStockOnly = this.props.inStockOnly;

    const rows = [];
    let lastCategory = null;

    this.props.products.forEach((product) => {
      if (product.name.indexOf(filterText) === -1) {
        return;
      }
      if (inStockOnly && !product.stocked) {
        return;
      }
      if (product.category !== lastCategory) {
        rows.push(
          
        );
      }
      rows.push(
        
      );
      lastCategory = product.category;
    });

    return (
      {rows}
Name Price
); } } class SearchBar extends React.Component { constructor(props) { super(props); this.handleFilterTextChange = this.handleFilterTextChange.bind(this); this.handleInStockChange = this.handleInStockChange.bind(this); } handleFilterTextChange(e) { this.props.onFilterTextChange(e.target.value); } handleInStockChange(e) { this.props.onInStockChange(e.target.checked); } render() { return (

{" "} Only show products in stock

); } } class FilterableProductTable extends React.Component { constructor(props) { super(props); this.state = { filterText: "", inStockOnly: false }; this.handleFilterTextChange = this.handleFilterTextChange.bind(this); this.handleInStockChange = this.handleInStockChange.bind(this); } handleFilterTextChange(filterText) { this.setState({ filterText: filterText }); } handleInStockChange(inStockOnly) { this.setState({ inStockOnly: inStockOnly }) } render() { return (
); } } const PRODUCTS = [ {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"}, {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"}, {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"}, {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"}, {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"}, {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"} ]; ReactDOM.render( , document.getElementById("container") );

到目前為止,我們已經(jīng)構(gòu)建了一個(gè)應(yīng)用程序,可以根據(jù)props和state正確地呈現(xiàn)在層次結(jié)構(gòu)中。現(xiàn)在是時(shí)候以另一種方式支持?jǐn)?shù)據(jù)流:深層次的表單組件需要更新FilterableProductTable中的狀態(tài)。

React使這個(gè)數(shù)據(jù)流清晰易懂,以便理解你的程序是如何工作的,但是它需要比傳統(tǒng)的雙向數(shù)據(jù)綁定更多的輸入。

如果你嘗試在當(dāng)前版本的示例中鍵入或選中該框,則會(huì)看到React忽略了你的輸入。這是故意的,因?yàn)槲覀円呀?jīng)將輸入的值prop設(shè)置為始終等于從FilterableProductTable傳入的state。

讓我們想想我們想要發(fā)生的事情。我們希望確保每當(dāng)用戶更改表單時(shí),我們都會(huì)更新?tīng)顟B(tài)以反映用戶的輸入。由于組件應(yīng)該只更新自己的state,只要state需要更新時(shí),FilterableProductTable就會(huì)傳遞回調(diào)到SearchBar。我們可以使用輸入上的onChange事件來(lái)通知它。 FilterableProductTable傳遞的回調(diào)將調(diào)用setState(),并且應(yīng)用程序?qū)⒈桓隆?/p>

雖然這聽(tīng)起來(lái)很復(fù)雜,但實(shí)際上只是幾行代碼。你的數(shù)據(jù)如何在整個(gè)應(yīng)用程序中流動(dòng)變得非常明確。

就是這樣

希望這篇文章可以讓你了解如何用React來(lái)構(gòu)建組件和應(yīng)用程序。雖然它可能比以前多一些代碼,但請(qǐng)記住,代碼的讀遠(yuǎn)遠(yuǎn)超過(guò)它的寫(xiě),并且讀取這個(gè)模塊化的顯式代碼非常容易。當(dāng)你開(kāi)始構(gòu)建大型組件庫(kù)時(shí),你將會(huì)體會(huì)到這種明確性和模塊性,并且通過(guò)代碼重用,你的代碼行將開(kāi)始縮小。

備注

文中所有示例的HTML和CSS內(nèi)容如下:

body {
  padding: 5px
}

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

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

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.16 - 淺入淺出 JavaScript 函數(shù)式編程

    摘要:函數(shù)式編程,一看這個(gè)詞,簡(jiǎn)直就是學(xué)院派的典范。所以這期周刊,我們就重點(diǎn)引入的函數(shù)式編程,淺入淺出,一窺函數(shù)式編程的思想,可能讓你對(duì)編程語(yǔ)言的理解更加融會(huì)貫通一些。但從根本上來(lái)說(shuō),函數(shù)式編程就是關(guān)于如使用通用的可復(fù)用函數(shù)進(jìn)行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數(shù)式編程(Functional Programming),一...

    csRyan 評(píng)論0 收藏0
  • React 核心思想之聲明式渲染

    摘要:模板北京時(shí)間數(shù)據(jù)渲染數(shù)據(jù)渲染將數(shù)據(jù)和模板綁定在渲染聲明式渲染和普通模板不同的是,模板寫(xiě)在文件中,而不是的標(biāo)簽中。創(chuàng)建模板容器類北京時(shí)間渲染指令數(shù)據(jù)只用于存放可變的數(shù)據(jù)。北京時(shí)間通過(guò)算法計(jì)算如何更新視圖。 React 發(fā)展很快,概念也多,本文目的在于幫助初學(xué)者理清 React 核心概念。 React 及 React 生態(tài) showImg(http://www.ruanyifeng.com...

    baiy 評(píng)論0 收藏0
  • Redux專題:考古

    摘要:光憑一個(gè)是無(wú)法實(shí)現(xiàn)血緣關(guān)系疏遠(yuǎn)的組件之間的狀態(tài)同步的。就是為解決這個(gè)問(wèn)題而生的。,處理動(dòng)作的派發(fā),相當(dāng)于架構(gòu)的。我們的主角是,它也是目前社區(qū)最受歡迎的狀態(tài)管理框架。專題一覽考古實(shí)用中間件時(shí)間旅行 本文是『horseshoe·Redux專題』系列文章之一,后續(xù)會(huì)有更多專題推出來(lái)我的 GitHub repo 閱讀完整的專題文章來(lái)我的 個(gè)人博客 獲得無(wú)與倫比的閱讀體驗(yàn) React的橫空出世給...

    toddmark 評(píng)論0 收藏0
  • React專題:不可變屬性

    摘要:沒(méi)有團(tuán)伙,單獨(dú)作案,干凈利落,便于封口。它最大的特點(diǎn)就是不可變。兄弟組件之間傳值原理和回調(diào)函數(shù)一樣,只不過(guò)這里父組件只是一個(gè)橋梁。父組件接收到回調(diào)函數(shù)的值以后,通過(guò)保存該值,并觸發(fā)另一個(gè)子組件重新渲染,重新渲染后另一個(gè)子組件便可以獲得該值。 本文是『horseshoe·React專題』系列文章之一,后續(xù)會(huì)有更多專題推出來(lái)我的 GitHub repo 閱讀完整的專題文章來(lái)我的 個(gè)人博客 ...

    biaoxiaoduan 評(píng)論0 收藏0
  • 前端進(jìn)階資源整理

    摘要:前端進(jìn)階進(jìn)階構(gòu)建項(xiàng)目一配置最佳實(shí)踐狀態(tài)管理之痛點(diǎn)分析與改良開(kāi)發(fā)中所謂狀態(tài)淺析從時(shí)間旅行的烏托邦,看狀態(tài)管理的設(shè)計(jì)誤區(qū)使用更好地處理數(shù)據(jù)愛(ài)彼迎房源詳情頁(yè)中的性能優(yōu)化從零開(kāi)始,在中構(gòu)建時(shí)間旅行式調(diào)試用輕松管理復(fù)雜狀態(tài)如何把業(yè)務(wù)邏輯這個(gè)故事講好和 前端進(jìn)階 webpack webpack進(jìn)階構(gòu)建項(xiàng)目(一) Webpack 4 配置最佳實(shí)踐 react Redux狀態(tài)管理之痛點(diǎn)、分析與...

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

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

0條評(píng)論

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