91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

React總結篇之二_設計高質量的React組件

發布時間:2020-09-05 04:05:34 來源:網絡 閱讀:2149 作者:cylcyl647308 欄目:web開發

一、易于維護組件的設計要素
1.組件劃分的原則:高內聚低耦合
(1)高內聚:將邏輯緊密相關的內容放在一個組件內。React可以將展示內容的JSX、定義行為的JavaScript代碼、甚至定義樣式的css,都可以放在一個JavaScript文件中,因此React天生具有高內聚的特點。
(2)低耦合:不同組件之間的依賴關系要盡量弱化,也就是每個組件要盡量獨立。


二、React組件的數據
1.數據分類:
React組件的數據分為兩種:prop和state。無論prop或者state改變,都可能引發React的重新渲染。那在設計一個組件時,什么時候選擇prop什么時候選擇state呢?原則很簡單:prop是組件的對外接口,state是組件的內部狀態,對外用prop,內部用state。

2.Prop:property的縮寫,是從外部傳遞給組件的數據,一個React組件通過定義自己能夠接受的prop就定義了自己的對外公共接口。我們先從外部世界看prop是如何使用的:
<SampleButton id="sample" borderWidth={2} onClick={onButtonClick} style={{color:"red"}}/> 上面創建了名為SampleButton的組件實例,使用了名字分別為id、borderWidth、onClick和style的prop。此處注意:HTML組件屬性的值都是字符串類型,即使是內嵌JavaScript,也依然是字符串形式表示代碼。但React組件的prop所能支持的類型除了字符串、可以是任何一種JavaScript語句支持的數據類型,如:數字類型、函數類型、style的值是一個包含color字段的對象,當prop的類型不是字符串類型時,在JSX中必須用花括號{}將prop值包住,所以style的值有兩層花括號,外層花括號代表的是JSX的語法,內層花括號表示這是一個對象常量。
Prop要反饋數據給外部世界,使用函數類型的prop,這等于父組件給了子組件一個回調函數,子組件在恰當的時機調用函數類型的prop,可以帶上必要額參數,這樣就把數據傳遞給外部世界。

3.React要求render函數只能返回一個元素!

4.組件內部接收傳入的prop:
(1)首先是構造函數,如下:
class Counter extends Component {
constructor(props){
super(props);
this.onClickIncrementButon = this.onClickIncrementButon.bind(this);
this.onClickDecrementButon = this.onClickDecrementButon.bind(this);
this.state = {
count : props.initValue || 0
}
}
}
注意:組件定義自己的構造函數,一定要在構造函數的第一行通過super調用父類也就是React.Component的構造函數;如果未調用,那么組件實例被構造之后,類實例的所有成員函數就無法通過this.props訪問到父組件傳過來的props值。很明顯,給this.props賦值是React.Component構造函數的工作之一。在Counter的構造函數中還給兩個成員函數綁定了當前this的執行環境,因為ES6方法創建的React類并不自動給我們綁定this到當前實例對象。

我的理解:
Component是React內的一個基類,用于繼承和創建React自定義組件。ES6規范下的面向對象實現起來非常精簡,class關鍵字可以快速創建一個類,而Component類內的所有屬性和方法均可以通過this訪問。換而言之,在Component內的任意方法內,可以通過this.xxx的方式調用該Component的其他屬性和方法。
constructor:類的默認方法,通過new命令生成對象實例時,自動調用該方法。一個類必須有constructor方法,如果沒有顯示定義,一個空的constructor方法會被默認添加;
super:子類必須在constructor方法中調用super方法,否則新建實例會報錯。這是因為子類自己的this對象,必須先通過父類的構造函數完成塑造,得到與父類同樣的屬性和方法,然后再對其加工,加上子類自己的實例屬性和方法。如果不調用super方法,子類就得不到this對象(子類是沒有自己的 this 對象的,它只能繼承自父類的 this 對象,然后對其進行加工,而super( )就是將父類中的this對象繼承給子類的。沒有 super,子類就得不到 this 對象);
super(props):在constructor中可以使用this.props;
this:在ES6語法下,類的每個成員函數在執行時的this并不是和類實例自動綁定的。而在構造函數中,this就是當前組件實例。所以,為了方便將來的調用,往往在構造函數中將這個實例的特定函數綁定this為當前實例。this.onClickIncrementButon = this.onClickIncrementButon.bind(this),就是通過bind方法讓當前實例中onClickIncrementButon函數被調用時,this始終指向當前組件實例

(2)讀取prop值:
在構造函數中可以通過props獲得傳入的prop值,在其他函數中可通過this.props訪問傳入prop的值。
const {caption} = this.props;
以上,我們使用了ES6的解構賦值語法,從this.props中獲得了名為caption的prop值。

5.propTypes檢查:
組件支持哪些prop;
每個prop應該是什么樣的格式;
如:對于Counter組件的propTypes定義代碼如下:
Counter.propTypes = {
caption : propTypes.string.isRquired,
initVlue : propTypes.number
}
其中要求caption必須是string類型,initVlue必須是number類型,另外,caption帶上了isRquired,表示使用Counter組件必須指定caption,而initVlue如果沒有也沒關系。
propTypes雖然能在開發階段發現代碼中的問題,但是放在產品環境就不大合適了:首先,占用一些代碼空間,耗CPU計算資源;其次,在產品環境下做propTypes檢查沒有什么幫助,在最終用戶的瀏覽器Console中輸出這些錯誤信息沒什么意義。所以,最好的方式是,開發者在代碼中定義propTypes,但在發布產品代碼時,用一種自動的方式將propTypes去掉。現有的babel-react-optimize具有這個功能,可以通過npm安裝,但是應該確保只在發布產品代碼時使用它。

6.初始化state:
通常在組件類的構造函數結尾處初始化state,如下:
constructor(props){
......
this.state = {
count:props.initValue || 0
}
}
因為initValue是一個可選的props,考慮到父組件沒有指定這個props值的情況,我們優先使用傳入屬性的initVlue,如果沒有,就使用默認值0。
組件的state必須是一個JavaScript對象!!!
以上,可使用React的defaultProps功能,如下:
Counter.defaultProps = {0}

7.改變組件的state,如下:
onClickIncrementButton () {
this.setState({count : this.state.count + 1})
}
在代碼中,this.state可以讀取到組件當前的state。注意:改變組件state必須要使用this.setState函數而不能直接去修改this.state。直接修改this.state的值,雖然事實上改變了組件的內部狀態,但只是野蠻的修改了state,并沒有驅動組件進行重新渲染,這樣就無法反應this.state值的變化;而this.setState()函數所做的事情,首先是改變this.state的值,然后驅動組件經歷更新過程,這樣才有機會讓this.state里新的值出現在界面上。

8.prop和state的對比

  • prop用于定義外部接口,state用于記錄內部狀態
  • prop的賦值在外部世界使用組件時,state的賦值在組件內部
  • 組件不應該改變prop的值,而state存在的目的就是讓組件來改變的
    組件的state存在就是為了被修改,每一次通過this.setState函數修改state就改變了組件的狀態,然后通過渲染過程把這種變化體現出來;
    但是,組件是絕不應該去修改傳入的props值的,假如父組件包含多個子組件,然后把一個JavaScript對象作為props傳給這幾個子組件,而某個組組件竟然改變了這個對象的內部值,那么,接下來其他子組件讀取這個對象會得到什么值呢?當時讀取了修改過的值,但是其他子組件是每次渲染都讀取這個props的值呢?還是只讀一次就用哪個最初的值呢?都有可能。也就是說一個子組件去修改props中的值,可能讓程序陷入一團混亂,違背了React設計的初衷
    UI = render(data)
    React組件扮演的是render函數的角色,應該是一個沒有副作用的純函數,修改props的值,是一個副作用,組件應該避免。
    嚴格來說,React并沒有辦法阻止你去修改傳入的props對象,所以,每個開發者就把這當做一個規定。

三、組件的生命周期
生命周期可能會經歷3個過程:

  • 裝載過程(Mount):組件第一次在DOM數中渲染的過程;
  • 更新過程(Update):組件被重新渲染的過程;
  • 卸載過程(Unmount):組件從DOM中刪除的過程。

1.裝載過程,依次調用的函數如下:

  • constructor
  • getInitialState
  • getDefaultProps
  • componentWillMount
  • render
  • componentDidMount

1.1 constructor
是ES6中每個類的構造函數,要創建一個組件類的實例,當然會調用對應的構造函數;
注意:無狀態的React組件不需要定義構造函數,一個組件需要構造函數,往往為下面的目的:
(1)初始化state,因為組件生命周期中任何函數都可能會訪問state,那整個生命周期中第一個被調用的構造函數自然是初始化state最理想的地方;
(2)綁定成員函數的this環境

1.2 getInitialState和getDefaultProps
待完成........

1.3 render
一個React組件必須要實現render函數,因為所有React組件的父類React.Component類對除render類之外的生命周期函數都有默認實現。
render函數并不做實際的渲染動作,而是返回一個JSX描述的結構,最終由React來操作渲染過程。某些特殊組件的作用不是渲染界面,或者,組件在某些情況下選擇沒有東西可畫,那就讓render函數返回一個null或者false,等于告訴React,這個組件這次不需要渲染任何DOM元素。
注意:render函數應該是一個純函數,完全根據this.props和this.state來決定返回的結果,而且不要產生任何副作用。在render中調用this.setState是錯的,因為一個純函數不應該引起狀態的改變。

1.4 componentWillMount和componentDidMount
在裝載過程中,componentWillMount在調用render之前被調用,componentDidMount在調用render之后被調用。
通常不用定義componentWillMount函數,所有可以在componentWillMount中做的事情都可以提前到constructor中去做。
而componentDidMount作用很大!render函數在調用完之后,componentDidMount并不是會被立刻調用,componentDidMount被調用的時候,render函數返回的東西已經引發了渲染,組件已經被裝載到了DOM樹上。由于render函數只返回一個JSX表示的對象,然后React庫根據返回對象來決定如何渲染。而React庫肯定要把所有組件返回的結果綜合起來,才知道如何產生對應的DOM修改,所以,當有多個組件時,只有React庫調用多個組件的render函數之后,才有可能完成裝載,這時才會依次調用各個組件的componentDidMount函數作為裝載過程的收尾。
兩者的區別:componentWillMount可以在服務器端被調用,也可以在瀏覽器端被調用,而componentDidMount只能在瀏覽器端被調用!

2.更新過程:
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
并不是所有的更新過程都會執行全部函數

2.1 componentWillReceiveProps(nextProps)
只要是父組件的render函數被調用,在render函數里面被渲染的子組件就會經歷更新過程,不管父組件傳給子組件的props有沒有改變,都會觸發子組件的componentWillReceiveProps。所以,這個函數有必要把傳入參數nextProps和this.props做對比,nextProps代表的是這一次渲染傳入的props值,this.props代表上一次渲染時的props值,只有兩者有變化的時候才調用this.setState更新內部狀態,這是提高React性能的重要方式。
注意:通過this.setState方法觸發的更新過程不會調用這個函數,這是因為這個函數適合根據新的props值(nextProps)來計算出是不是要更新內部狀態state。更新組件內部狀態的方法就是this.setState,如果this.setState的調用導致componentWillReceiveProps再一次被調用,那就是一個死循環了。

2.2 shouldComponentUpdate(nextProps,nextState)
render和shouldComponentUpdate是React生命周期函數中唯二兩個要求有返回結果的函數。render函數返回的結果用于構造DOM對象,而shouldComponentUpdate返回一個布爾值,告訴React庫這個組件在這次更新過程中是否要繼續。
在更新過程中,React庫首先調用shouldComponentUpdate函數,若返回true,會繼續更新過程,接著調用render函數,若是false,停止更新過程。另外,通過this.setState函數引發更新過程,并不是立刻更新組件的state值,在執行到函數shouldComponentUpdate的時候,this.state依然是this.setState函數執行之前的值,因此,在shouldComponentUpdate函數中,可進行比較nextProps、nextState、this.props、this.state是否發生變化,若變化則繼續更新,是提高React性能的重要方式。

2.3 componentWillUpdate和componentDidUpdate
如果shouldComponentUpdate返回true,React接下來會依次調用對應組件的componentWillUpdate、render和componentDidUpdate函數。
和裝載過程不同的是,當在服務器端使用React渲染時,componentDidUpdate函數并不是只在瀏覽器端才執行的。無論更新過程發生在服務器端還是瀏覽器端,該函數都會被調用。

3.卸載過程
componentWillUnmount
當React組件要從DOM樹上刪除掉之前,對應的componentWillUnmount會被調用,所以該函數適合做一些請理性的工作。
componentWillUnmount往往和componentDidMount有關,比如,在componentDidMount用非React的方法創造了一些DOM元素,如果不管可能會造成內存泄漏,那就需要在componentWillUnmount中將這些創建的DOM元素清理掉。


四、組件向外傳遞數據
1.React中state和prop的局限
React使用state來存儲狀態的一個缺點就是:數據的冗余和重復,另外使用prop在多個父子組件中傳遞數據時也有同樣的問題。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

临海市| 万山特区| 彰化县| 辉南县| 奉新县| 包头市| 皋兰县| 汤阴县| 彰化县| 南丰县| 普宁市| 锡林郭勒盟| 徐闻县| 错那县| 庆安县| 宜宾市| 千阳县| 新和县| 太仓市| 湘乡市| 扶绥县| 大渡口区| 武威市| 耿马| 东光县| 体育| 达拉特旗| 阿城市| 太原市| 读书| 延安市| 淄博市| 樟树市| 冀州市| 长武县| 长汀县| 满城县| 文登市| 石泉县| 上饶县| 凤庆县|