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

資訊專欄INFORMATION COLUMN

React編程思想

ckllj / 399人閱讀

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

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

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

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

從設(shè)計稿開始

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

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分解為組件并分析層級結(jié)構(gòu)

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

但我們怎么知道自己的組件應(yīng)該是什么?只需要使用一些通用的技巧來決定是否應(yīng)該創(chuàng)建一個新的函數(shù)或?qū)ο?。其中一個技巧叫做:單一責(zé)任原則。就是說,在理想情況下,一個組件應(yīng)該只用來完成一件事。若非如此,則應(yīng)該考慮將其分解成更小的子組件。

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

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

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

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

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

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

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

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

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

FilterableProductTable

SearchBar

ProductTable

ProductCategoryRow

ProductRow

第二步:用React構(gòu)建一個靜態(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),接下來可以實現(xiàn)應(yīng)用程序了。最初的方案是構(gòu)建一個使用數(shù)據(jù)模型渲染UI但不具有交互性的版本。最好將靜態(tài)版本和添加交互性進(jìn)行解耦,因為構(gòu)建一個靜態(tài)的版本需要大量的輸入?yún)s不需要思考,而增加交互性需要大量的思考而不需要很多輸入。我們一會兒會知道為什么。

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

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

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

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

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

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

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

用戶輸入的搜索文本

復(fù)選框的值

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

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

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

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

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

原來的產(chǎn)品清單是作為props傳入的,所以這不是state。搜索文本和復(fù)選框似乎是state,因為它們隨著時間而改變,不能從任何東西計算。最后,產(chǎn)品的過濾列表不是state,因為它可以通過將產(chǎn)品的原始列表與復(fù)選框的搜索文本和值組合來計算得到。

所以最后,我們的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。接下來,我們需要確定哪個組件會改變或擁有這個state。

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

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

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

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

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

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

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

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

通用所有者組件是FilterableProductTable

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

酷,所以我們已經(jīng)決定,我們的state存活在FilterableProductTable中。首先,將一個實例屬性this.state = {filterText:"",inStockOnly:false}添加到FilterableProductTable的構(gòu)造函數(shù)中,以反映應(yīng)用程序的初始狀態(tài)。然后,將filterTextinStockOnly作為prop傳遞給ProductTableSearchBar。最后,使用這些props來篩選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)建了一個應(yīng)用程序,可以根據(jù)props和state正確地呈現(xiàn)在層次結(jié)構(gòu)中?,F(xiàn)在是時候以另一種方式支持?jǐn)?shù)據(jù)流:深層次的表單組件需要更新FilterableProductTable中的狀態(tài)。

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

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

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

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

就是這樣

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

備注

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

body {
  padding: 5px
}

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

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

相關(guān)文章

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

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

    csRyan 評論0 收藏0
  • React 核心思想之聲明式渲染

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

    baiy 評論0 收藏0
  • Redux專題:考古

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

    toddmark 評論0 收藏0
  • React專題:不可變屬性

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

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

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

    BlackMass 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<