日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iShow UI for React 最佳实践

發布時間:2025/3/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iShow UI for React 最佳实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

React 與 AJAX

React只負責處理View這一層,它本身不涉及網絡請求/AJAX,所以這里我們需求考慮兩個問題:

  • 第一,用什么技術從服務端獲取數據;

  • 第二,獲取到的數據應該放在react組件的什么位置。

React官方提供了一種解決方案:Load Initial Data via AJAX

使用jQuery的Ajax方法,在一個組件的componentDidMount()中發ajax請求,拿到的數據存在組件自己的state中,并調用setState方法去更新UI。如果是異步獲取數據,則在componentWillUnmount中取消發送請求。

如果只是為了使用jQuery的Ajax方法就引入整個jQuery庫,既是一種浪費又加大了整個應用的體積。那我們還有什么其他的選擇嗎?事實上是有很多的:fetch()、fetch polyfill、axios...其中最需要我們關注的是window.fetch(),它是一個簡潔、標準化的javascript的Ajax API。在Chrome和Firefox中已經可以使用,如果需要兼容其他瀏覽器,可以使用fetch polyfill。

React官方文檔只告訴了我們在一個單一組件中如何通過ajax從服務器端獲取數據,但并沒有告訴我們在一個完整的實際項目中到底應該把數據存在哪些組件中,這部分如果缺乏規范的話,會導致整個項目變得混亂、難以維護。下面給出三種比較好的實踐:

1. 所有的數據請求和管理都存放在唯一的一個根組件

讓父組件/根組件集中發送所有的ajax請求,把從服務端獲取的數據統一存放在這個組件的state中,再通過props把數據傳給子組件。這種方法主要是針對組件樹不是很復雜的小型應用。缺點就是當組件樹的層級變多了以后,需要把數據一層一層地傳給子組件,寫起來麻煩,性能也不好。

2. 設置多個容器組件專門處理數據請求和管理

其實跟第一種方法類似,只不過設置多個容器組件來負責數據請求和狀態管理。這里我們需要區分兩種不同類型的組件,一種是展示性組件(presentational component),另一種是容器性組件(container component)。展示性組件本身不擁有任何狀態,所有的數據都從容器組件中獲得,在容器組件中發送ajax請求。兩者更詳細的描述,可以閱讀下這篇文章:Presentational and Container Components

一個具體的例子:

假設我們需要展示用戶的姓名和頭像,首先創建一個展示性組件<UserProfile />,它接受兩個Props:name和profileImage。這個組件內部沒有任何關于Ajax的代碼。

然后創建一個容器組件<UserProfileContainer />,它接受一個userId的參數,發送Ajax請求從服務器獲取數據存在state中,再通過props傳給<UserProfile />組件。

3. 使用Redux或Relay的情況

Redux管理狀態和數據,Ajax從服務器端獲取數據,所以很顯然當我們使用了Redux時,應該把所有的網絡請求都交給redux來解決。具體來說,應該是放在Async Actions。如果用其他類Flux庫的話,解決方式都差不多,都是在actions中發送網絡請求。

Relay是Facebook官方推出的一個庫。如果用它的話,我們只需要通過GraphQL來聲明組件需要的數據,Relay會自動地把下載數據并通過props往下傳遞。不過想要用Relay,你得先有一個GraphQL的服務器...

一個標準組件的組織結構

1 class definition1.1 constructor 1.1.1 event handlers 1.2 'component' lifecycle events 1.3 getters 1.4 render 2 defaultProps 3 proptypes

示例:

class Person extends React.Component { constructor (props) { super(props); this.state = { smiling: false }; this.handleClick = () => { this.setState({smiling: !this.state.smiling}); }; } componentWillMount () { // add event listeners (Flux Store, WebSocket, document, etc.) }, componentDidMount () { // React.getDOMNode() }, componentWillUnmount () { // remove event listeners (Flux Store, WebSocket, document, etc.) }, get smilingMessage () { return (this.state.smiling) ? "is smiling" : ""; } render () { return ( <div onClick={this.handleClick}> {this.props.name} {this.smilingMessage} </div> ); }, } Person.defaultProps = { name: 'Guest' }; Person.propTypes = { name: React.PropTypes.string };

以上示例代碼的來源:https://github.com/planningcenter/react-patterns#component-organization

使用 PropTypes 和 getDefaultProps()

  • 一定要寫PropTypes,切莫為了省事而不寫

  • 如果一個Props不是requied,一定在getDefaultProps中設置它

    React.PropTypes主要用來驗證組件接收到的props是否為正確的數據類型,如果不正確,console中就會出現對應的warning。出于性能方面的考慮,這個API只在開發環境下使用。

  • 基本使用方法:

    propTypes: {myArray: React.PropTypes.array,myBool: React.PropTypes.bool,myFunc: React.PropTypes.func, myNumber: React.PropTypes.number, myString: React.PropTypes.string, // You can chain any of the above with `isRequired` to make sure a warning // is shown if the prop isn't provided. requiredFunc: React.PropTypes.func.isRequired }

    假如我們props不是以上類型,而是擁有復雜結構的對象怎么辦?比如下面這個:

    {text: 'hello world',numbers: [5, 2, 7, 9], }

    當然,我們可以直接用React.PropTypes.object,但是對象內部的數據我們卻無法驗證。

    propTypes: {myObject: React.PropTypes.object, }

    進階使用方法:shape()?和?arrayOf()

    propTypes: {myObject: React.PropTypes.shape({text: React.PropTypes.string,numbers: React.PropTypes.arrayOf(React.PropTypes.number), }) }

    下面是一個更復雜的Props:

    [{ name: 'Zachary He', age: 13, married: true, }, { name: 'Alice Yo', name: 17, }, { name: 'Jonyu Me', age: 20, married: false, } ]

    綜合上面,寫起來應該就不難了:

    propTypes: {myArray: React.PropTypes.arrayOf(React.propTypes.shape({name: React.propTypes.string.isRequired, age: React.propTypes.number.isRequired, married: React.propTypes.bool }) ) }

    把計算和條件判斷都交給?render()?方法吧

    1. 組件的state中不能出現props
    // BAD:constructor (props) {this.state = {fullName: `${props.firstName} ${props.lastName}` }; } render () { var fullName = this.state.fullName; return ( <div> <h2>{fullName}</h2> </div> ); } // GOOD: render () {var fullName = `${this.props.firstName} ${this.props.lastName}`; }

    當然,復雜的display logic也應該避免全堆放在render()中,因為那樣可能導致整個render()方法變得臃腫,不優雅。我們可以把一些復雜的邏輯通過helper function移出去。

    // GOOD: helper function renderFullName () {return `${this.props.firstName} ${this.props.lastName}`; }render () {var fullName = this.renderFullName(); }
    2. 保持state的簡潔,不要出現計算得來的state
    // WRONG:constructor (props) {this.state = {listItems: [1, 2, 3, 4, 5, 6], itemsNum: this.state.listItems.length }; } render() { return ( <div> <span>{this.state.itemsNum}</span> </div> ) } // Right: render () {var itemsNum = this.state.listItems.length; }
    3. 能用三元判斷符,就不用If,直接放在render()里
    // BAD: renderSmilingStatement () {if (this.state.isSmiling) {return <span>is smiling</span>; }else { return ''; } }, render () { return <div>{this.props.name}{this.renderSmilingStatement()}</div>; } // GOOD: render () {return (<div>{this.props.name}{(this.state.smiling)? <span>is smiling</span> : null } </div> ); }
    4. 布爾值都不能搞定的,交給IIFE吧

    Immediately-invoked function expression

    return (<section><h1>Color</h1><h3>Name</h3><p>{this.state.color || "white"}</p> <h3>Hex</h3> <p> {(() => { switch (this.state.color) { case "red": return "#FF0000"; case "green": return "#00FF00"; case "blue": return "#0000FF"; default: return "#FFFFFF"; } })()} </p> </section> );
    5. 不要把display logic寫在componentWillReceiveProps或componentWillMount中,把它們都移到render()中去。

    如何動態處理 classNames

    1. 使用布爾值
    // BAD: constructor () { this.state = { classes: [] }; } handleClick () { var classes = this.state.classes; var index = classes.indexOf('active'); if (index != -1) { classes.splice(index, 1); } else { classes.push('active'); } this.setState({ classes: classes }); } // GOOD:constructor () { this.state = { isActive: false }; } handleClick () { this.setState({ isActive: !this.state.isActive }); }
    2. 使用classnames這個小工具來拼接classNames:
    // BEFORE: var Button = React.createClass({render () {var btnClass = 'btn';if (this.state.isPressed) btnClass += ' btn-pressed'; else if (this.state.isHovered) btnClass += ' btn-over'; return <button className={btnClass}>{this.props.label}</button>; } }); // AFTER: var classNames = require('classnames');var Button = React.createClass({render () {var btnClass = classNames({ 'btn': true, 'btn-pressed': this.state.isPressed, 'btn-over': !this.state.isPressed && this.state.isHovered }); return <button className={btnClass}>{this.props.label}</button>; } });

    轉載于:https://www.cnblogs.com/yuri2016/p/8890596.html

    總結

    以上是生活随笔為你收集整理的iShow UI for React 最佳实践的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。