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

資訊專欄INFORMATION COLUMN

React思維方式·譯

helloworldcoding / 2341人閱讀

摘要:搜索文本和多選框因?yàn)闀l(fā)生變化,且不能通過計(jì)算得出,所以是狀態(tài)。最后,過濾過的產(chǎn)品列表,可以通過原始產(chǎn)品列表搜索文本和多選框值計(jì)算出來,因此它不是狀態(tài)。從傳入的回調(diào)函數(shù)會調(diào)用,從而更新組件。

在使用JavaScript開發(fā)大型、快速的網(wǎng)頁應(yīng)用時(shí),React是我們的首選。在Facebook和Instagram,React很好地減少了我們的工作量。
React最強(qiáng)大部分之一,是讓你在開發(fā)應(yīng)用的同時(shí),按照開發(fā)應(yīng)用的思路去思考。這篇文章,將指導(dǎo)你通過幾個(gè)步驟,用React開發(fā)一個(gè)可搜索數(shù)據(jù)表

從一個(gè)模型開始

假設(shè)我們已經(jīng)有了一個(gè)JSON API和一個(gè)設(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分解為組件結(jié)構(gòu)

首先,在模型圖上框處每個(gè)組件(和子組件),并給組件命名。如果與設(shè)計(jì)師一起工作,他可能已經(jīng)心中有數(shù),不妨和他聊聊。他們Photoshop圖層名可能就能成為你的組件名!

但如何劃分父組件子組件呢?就像創(chuàng)建一個(gè)函數(shù)或?qū)ο笠粯印F渲兄皇菃我宦氊?zé)原則,理想情況下,一個(gè)組件僅做一件事。如果一個(gè)組件太大,它應(yīng)該被分解為更小的子組件。

如果經(jīng)常把JSON數(shù)據(jù)模型展現(xiàn)給用戶,你會發(fā)現(xiàn),若模型創(chuàng)建正確,UI(以及組件結(jié)構(gòu))能很好的反映數(shù)據(jù)。這是因?yàn)閁I和數(shù)據(jù)模型一定程度都是依附于信息架構(gòu)的,這意味著,將UI分解為組件并不是最重要的,最重要的是,被分解的組件能準(zhǔn)確表現(xiàn)你數(shù)據(jù)模型的一部分。

可以看出,我們的app有五個(gè)組件,我們用斜體表示每個(gè)組件所代表的數(shù)據(jù)。

FilterableProducTable(可過濾產(chǎn)品表,橙色):包含整個(gè)示例

SearchBar(搜索欄,藍(lán)色):接收用戶輸入

ProductTable(產(chǎn)品表,綠色):根據(jù)用戶輸入,展示和過濾數(shù)據(jù)集

ProductCategoryRow(產(chǎn)品分類行,藍(lán)綠色):顯示為每個(gè)分類的頭部

ProductRow(產(chǎn)品行,紅色):每個(gè)產(chǎn)品顯示為一行

觀察ProductTable,你會發(fā)現(xiàn)表頭(包含“Name”和“Price”標(biāo)簽部分)未被劃分為一個(gè)組件。表頭是否做為組件屬于個(gè)人偏好,至于使用哪種方式,以下可以作為參考。本例中,表頭作為ProductTable的一部分,因?yàn)楸眍^屬于渲染的數(shù)據(jù)集的一部分,所以表頭在ProductTable的職責(zé)范圍內(nèi)。但如果表頭變得更為復(fù)雜(如為添加排序功能),將表頭分離為ProductTableHeader更合理。

現(xiàn)在,我們已經(jīng)將模型劃分為了組件,接著要安排組件的層次結(jié)構(gòu)。這并不難,模型中一個(gè)組件出現(xiàn)在另一個(gè)組件的內(nèi)部,在層次結(jié)構(gòu)呈現(xiàn)為它的一個(gè)子級。

FilterableProductTable

SearchBar

ProductTable

ProductCategeoryRow

ProductRow

第二步:創(chuàng)建React靜態(tài)版本
class ProductCategoryRow extends React.Component {
  render() {
    return {this.props.category};
  }
}

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

class ProductTable extends React.Component {
  render() {
    var rows = [];
    var lastCategory = null;
    this.props.products.forEach(function(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 (
); } } var 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),是時(shí)候?qū)崿F(xiàn)這個(gè)app了。最簡單的方式,利用數(shù)據(jù)模型渲染一個(gè)無交互的UI版本。創(chuàng)建組件靜態(tài)版本需要敲很多鍵盤,無需過多思考,而添加交互效果需要很多思考,不需要敲很多鍵盤,這正是極好的解耦過程。

用數(shù)據(jù)模型創(chuàng)建app的靜態(tài)版本,你在創(chuàng)建組件時(shí)會想著復(fù)用其它組件,想著用屬性來傳遞數(shù)據(jù),而屬性是父級向子級傳遞數(shù)據(jù)的方式。即便你熟悉狀態(tài)的概念,創(chuàng)建靜態(tài)版本時(shí)也不要用任何狀態(tài)。狀態(tài)僅用作交互,狀態(tài)數(shù)據(jù)隨時(shí)間而變化,因?yàn)殪o態(tài)版本無需任何交互,所以沒必要使用任何狀態(tài)。

在層級結(jié)構(gòu)中,既可以自上而下開始創(chuàng)建組件(從FilterableProductTable開始),也可以自下而上開始創(chuàng)建組件(從ProductRow開始)。簡單的例子中,自上而下的方式往往更簡單,對于大型項(xiàng)目來說,自下而上的方式更簡單,更容易測試。

該步完成時(shí),你已經(jīng)有了一些可復(fù)用的組件,這些組件渲染了你的數(shù)據(jù)模型。靜態(tài)版本的組件僅有render()方法。頂層組件(FilterableProductTable)會把數(shù)據(jù)模型作為一個(gè)屬性。如果數(shù)據(jù)模型發(fā)生變化,再次調(diào)用ReactDOM.render(),UI會被更新。你可以很容易的看出UI是如何被更新的,哪兒發(fā)生了改變。React的單向數(shù)據(jù)流(也叫單向數(shù)據(jù)綁定),使得一切變得模塊化,變得快速。

簡述:屬性與狀態(tài)

屬性和狀態(tài)是React中的兩種數(shù)據(jù)模型,理解兩者的區(qū)別非常重要。如果你無法確定兩者的區(qū)別,請瀏覽官方文檔

第三步:確定描述UI的最少狀態(tài)

為了讓UI可以交互,需要能夠觸發(fā)數(shù)據(jù)模型發(fā)生改變。React的狀態(tài)能讓此變得簡單。

為了能正確的創(chuàng)建app,你要考慮app需要的最少狀態(tài)。關(guān)鍵在于不重復(fù),使用最少的狀態(tài),計(jì)算出所有你需要的數(shù)據(jù)。例如,你創(chuàng)建一個(gè)TODO列表,只需要保留一個(gè)TODO項(xiàng)數(shù)組,不需要再使用一個(gè)變量來保存TODO項(xiàng)數(shù)量,當(dāng)你需要渲染TODO項(xiàng)數(shù)目時(shí),使用TODO項(xiàng)數(shù)組長度即可。

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

原始產(chǎn)品列表

用戶輸入的搜索文本

多選框的值

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

簡單地問三個(gè)問題,讓我們過一遍,看看哪些是狀態(tài):

是否為從父組件傳入的屬性?如果是,或許不是狀態(tài)

是否是隨時(shí)間不變的?如果是,或許不是狀態(tài)

是否能通過組件中的其他狀態(tài)或?qū)傩杂?jì)算出來?如果是,不是狀態(tài)

原始產(chǎn)品列表是從屬性傳入的,因此不是狀態(tài)。搜索文本和多選框因?yàn)闀l(fā)生變化,且不能通過計(jì)算得出,所以是狀態(tài)。最后,過濾過的產(chǎn)品列表,可以通過原始產(chǎn)品列表、搜索文本和多選框值計(jì)算出來,因此它不是狀態(tài)。

最終,我們的狀態(tài)有:

用戶輸入的搜索文本

多選框的值

第四步:確定狀態(tài)應(yīng)該放置的位置
class ProductCategoryRow extends React.Component {
  render() {
    return ({this.props.category});
  }
}

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

class ProductTable extends React.Component {
  render() {
    var rows = [];
    var lastCategory = null;
    this.props.products.forEach((product) => {
      if (product.name.indexOf(this.props.filterText) === -1 || (!product.stocked && this.props.inStockOnly)) {
        return;
      }
      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 { constructor(props) { super(props); this.state = { filterText: "", inStockOnly: false }; } render() { return (
); } } var 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") );

OK,我們已經(jīng)確定了app的最少狀態(tài)。接下來,我們要確定哪個(gè)組件是可變的,或者說狀態(tài)屬于哪個(gè)組件。

記住,React在層級及結(jié)構(gòu)中,數(shù)據(jù)向下流動(dòng)。這或許不能馬上清楚狀態(tài)究竟屬于哪個(gè)組件。這經(jīng)常也是初學(xué)者認(rèn)識React最有挑戰(zhàn)性的部分。所以,按照以下步驟,弄清這個(gè)問題:

對于應(yīng)用中的每個(gè)狀態(tài):

確認(rèn)每個(gè)需要這個(gè)狀態(tài)進(jìn)行渲染的組件

找到它們共有的父組件(層級結(jié)構(gòu)中,所有需要這個(gè)狀態(tài)的組件之上的組件)

讓共有父組件,或者比共有父組件更高層級的組件持有該狀態(tài)

如果你找不到合適的組件持有該狀態(tài),創(chuàng)建一個(gè)新的組件,簡單持有該狀態(tài)。把這個(gè)組件插入層級結(jié)構(gòu)共有父組件之上

將這個(gè)策略用到我們的應(yīng)用中:

ProductTable要根據(jù)狀態(tài)過濾產(chǎn)品列表,SearchBar要顯示搜索文本和多選框狀態(tài)

共有父組件是FilterableProductTable

FilterableProductTable持有過濾文本和多選框值很合理

Cool,就這樣決定把狀態(tài)放置到FilterableProductTable。首先,在FilterableProductTableconstructor中添加示例屬性this.state = {filterText: "", inStockOnly: false} ,來初始化狀態(tài)。然后,將filterTextisStockOnly作為屬性傳入ProductTableSearchBar。最后,使用這些屬性過濾ProductTable中的行,和設(shè)置SearchBar中表單的值

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

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

class ProductTable extends React.Component {
  render() {
    var rows = [];
    var lastCategory = null;
    this.props.products.forEach((product) => {
      if (product.name.indexOf(this.props.filterText) === -1 || (!product.stocked && this.props.inStockOnly)) {
        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.handleChange = this.handleChange.bind(this); } handleChange() { this.props.onUserInput( this.filterTextInput.value, this.inStockOnlyInput.checked ); } render() { return (
this.filterTextInput = input} onChange={this.handleChange} />

this.inStockOnlyInput = input} onChange={this.handleChange} /> {" "} Only show products in stock

); } } class FilterableProductTable extends React.Component { constructor(props) { super(props); this.state = { filterText: "", inStockOnly: false }; this.handleUserInput = this.handleUserInput.bind(this); } handleUserInput(filterText, inStockOnly) { this.setState({ filterText: filterText, inStockOnly: inStockOnly }); } render() { return (
); } } var 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)用屬性和狀態(tài),創(chuàng)建了具有在層級結(jié)構(gòu)中至上而下的數(shù)據(jù)流?,F(xiàn)在,是時(shí)候支持反向的數(shù)據(jù)流動(dòng),讓底層表單組件能夠更新FilterableProductTable中的狀態(tài)。

React的單向數(shù)據(jù)流動(dòng)使得程序更加清晰易懂,但相比雙向數(shù)據(jù)綁定,確實(shí)需要多打些代碼。

如果你嘗試在當(dāng)前示例中,輸入文本或選擇多選框,會發(fā)現(xiàn)React忽略了你的輸入。這是故意的,因?yàn)槲覀円O(shè)置inputvalue屬性要恒等于FilterableProductTable傳入的狀態(tài)。

思考下我們期望的狀況。我們希望,表單中無論何時(shí)發(fā)生改變,用戶的輸入要能夠更新狀態(tài)。因?yàn)榻M件應(yīng)該只更新自己的狀態(tài),所以FilterableProductTable會將回調(diào)函數(shù)傳遞給SearchBar,SearchBar會在要更新狀態(tài)時(shí)調(diào)用回調(diào)函數(shù)。我們用onChange事件通知狀態(tài)更新。從FilterableProductTable傳入的回調(diào)函數(shù)會調(diào)用setState(),從而更新組件。

雖然聽起來有點(diǎn)復(fù)雜,但是也就添加幾行代碼。它非常清晰地表現(xiàn)出了app中的數(shù)據(jù)流動(dòng)。

就這樣

希望此文能帶給你使用React創(chuàng)建組件和應(yīng)用的思路。盡管你可能需要打比平時(shí)更多的代碼,但記住,代碼看著總是遠(yuǎn)比打著的時(shí)候多,并且這些代碼都是模塊化、清晰而易讀的。當(dāng)你開始開發(fā)大型組件庫的時(shí)候,你將會慶幸React的數(shù)據(jù)流清晰和模塊化的特性,并且隨著代碼的復(fù)用,代碼規(guī)模會開始縮小。

原文鏈接

thinking-in-react

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

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

相關(guān)文章

  • ()React hooks:它不是一種魔法,只是一個(gè)數(shù)組——使用圖表揭秘提案規(guī)則

    摘要:它并不是實(shí)際在內(nèi)部的工作方式,而且它只是一個(gè)提案,在未來都會有可能發(fā)生變化。這意味著,數(shù)據(jù)的存儲是獨(dú)立于組件之外的。因此,有一個(gè)訣竅就是你需要思考作為一組需要一個(gè)匹配一致的指針去管理的數(shù)組染陌譯。 原文地址:https://medium.com/@ryardley/... 譯文:染陌 (Github) 譯文地址:https://github.com/answershuto/Blog 轉(zhuǎn)...

    fjcgreat 評論0 收藏0
  • 】渲染Elements

    摘要:注不做翻譯是中最小的構(gòu)建部件。在里渲染讓我們看一下在下面有在你文件中無處不在的標(biāo)簽我們會把這元素成為元素因?yàn)榈乃袞|西都會放在這個(gè)元素里面。通過方法,我們能吧渲染到我們根節(jié)點(diǎn)上。更新被渲染的是不可變的。 下面是react官方文檔的個(gè)人翻譯,如有翻譯錯(cuò)誤,請多多指出原文地址:https://facebook.github.io/re...特別感謝Hevaen,同時(shí)也向豪大React群所有...

    LoftySoul 評論0 收藏0
  • [] 前端攻略-從路人甲到英雄無敵二:JavaScript 與不斷演化的框架

    摘要:一般來說,聲明式編程關(guān)注于發(fā)生了啥,而命令式則同時(shí)關(guān)注與咋發(fā)生的。聲明式編程可以較好地解決這個(gè)問題,剛才提到的比較麻煩的元素選擇這個(gè)動(dòng)作可以交托給框架或者庫區(qū)處理,這樣就能讓開發(fā)者專注于發(fā)生了啥,這里推薦一波與。 本文翻譯自FreeCodeCamp的from-zero-to-front-end-hero-part。 繼續(xù)譯者的廢話,這篇文章是前端攻略-從路人甲到英雄無敵的下半部分,在...

    roadtogeek 評論0 收藏0
  • 1月份前端資源分享

    摘要:更多資源請文章轉(zhuǎn)自月份前端資源分享視頻前端技術(shù)論壇融合不可錯(cuò)過的迷你庫測試框架實(shí)例教程為你詳細(xì)解讀請求頭的具體含意解析的庫如果要用前端框架,開發(fā)流程是怎樣的與有什么區(qū)別正確使用的方法是什么流程圖插件小如何讓元素只能輸入純文本前端技術(shù)中 更多資源請Star:https://github.com/maidishike... 文章轉(zhuǎn)自:https://github.com/jsfront...

    solocoder 評論0 收藏0
  • []學(xué)習(xí)如何去學(xué)習(xí) JavaScript - 5 個(gè)你應(yīng)該如何花在學(xué)習(xí) JS 上時(shí)間的建議

    摘要:擁抱異步編程縱觀發(fā)展史也可以說成開發(fā)的發(fā)展史,你會發(fā)現(xiàn)異步徹底改變了這場游戲??梢赃@么說,異步編程已成為開發(fā)的根基。這也是你應(yīng)盡早在上投入大量時(shí)間的一處核心知識點(diǎn),這其中包含和等重要概念。這也是最突出的一項(xiàng)貢獻(xiàn)。 原文地址:Medium - Learning How to Learn JavaScript. 5 recommendations on how you should spend ...

    wanglu1209 評論0 收藏0

發(fā)表評論

0條評論

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