當咱們在說組件抽象與複用的時候咱們在說什麼?本質就是組件的拆分。。css
「分而治之」是一個好策略。可是不要濫用,只有必要的時候纔去拆分組件, 否則可能得不償失 。html
高內聚:就是把邏輯緊密相關的內容放在一個組件中。這段js,css,html都是爲了實現同一個功能咱們把它放在一個js文件裏。react天生具備高內聚的特色。react
低耦合:指的是不一樣組件之間的依賴關係要儘可能弱化,也就是每一個組件要儘可能獨立 。 保持整個系統的低耦合度,須要對系統中的功能有充分的認識,而後根據功能點劃分模 塊,讓不一樣的組件去實現不一樣的功能json
劃分依據是根據組件的定義方式。redux
// 函數組件
function Hello(props) {
return <h1>Hello, {props.name}</h1>;
}
// 類組件
class Hello extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
複製代碼
類組件能夠維護自身的狀態變量,即組件的state,類組件還有不一樣的生命週期方法,可讓開發者可以在組件的不一樣階段(掛載、更新、卸載),對組件作更多的控制。 類組件這麼強大,首選類組件? 不,函數組件更加專一和單一,承擔的職責也更加清晰,它只是一個返回React 元素的函數,只關注對應UI的展示。函數組件接收外部傳入的props,返回對應UI的DOM描述,僅此而已。 函數組件的使用能夠從思想上迫使你在設計組件時多作思考,更加關注邏輯和顯示的分離,設計出更加合理的頁面上組件樹的結構。實際操做上,當一個組件不須要管理自身狀態時,能夠把它設計成函數組件,當你有足夠的理由發現它須要「升級」爲類組件時,再把它改造爲類組件。api
劃分依據是根據組件內部是否維護state。無狀態組件內部不使用state,只根據外部組件傳入的props返回待渲染的React 元素。有狀態組件內部使用state,維護自身狀態的變化,有狀態組件根據外部組件傳入的props和自身的state,共同決定最終返回的React 元素。函數組件必定是無狀態組件,類組件則既能夠充當無狀態組件,也能夠充當有狀態組件數組
劃分依據是根據組件的職責.bash
展現型組件的職責是:組件UI長成什麼樣。展現型組件不關心組件使用的數據是如何獲取的,以及組件數據應該如何修改,它只須要知道有了這些數據後,組件UI是什麼樣子的便可。外部組件經過props傳遞給展現型組件所需的數據和修改這些數據的回調函數,展現型組件只是它們的使用者。展現型組件通常是無狀態組件,不須要state,由於展現型組件不須要管理數據,但當展現型組件須要管理自身的UI狀態時,例如控制組件內部彈框的顯示與隱藏,是可使用state的,這時的state屬於UI state。既然大部分狀況下展現型組件不須要state,應該優先考慮使用函數組件實現展現型組件。app
容器型組件的職責是:組件數據如何工做。容器型組件須要知道如何獲取子組件所需數據,以及這些數據的處理邏輯,並把數據和邏輯經過props提供給子組件使用。容器型組件通常是有狀態組件,由於它們須要管理頁面所需數據。less
class UserListContainer extends React.Component{
constructor(props){
super(props);
this.state = {
users: []
}
}
componentDidMount() {
var that = this;
fetch('/path/to/user-api').then(function(response) {
response.json().then(function(data) {
that.setState({users: data})
});
});
}
render() {
return (
<UserList users={this.state.users} />
)
}
}
function UserList(props) {
return (
<div>
<ul className="user-list">
{props.users.map(function(user) {
return (
<li key={user.id}>
<span>{user.name}</span>
</li>
);
})}
</ul>
</div>
)
}
複製代碼
這三組概念都體現了關注點分離的思想:UI展示和數據邏輯的分離。函數組件、無狀態組件和展現型組件主要關注UI展示,類組件、有狀態組件和容器型組件主要關注數據邏輯。
它們之間的關聯關係能夠概括爲:函數組件必定是無狀態組件,展現型組件通常是無狀態組件;類組件既能夠是有狀態組件,又能夠是無狀態組件,容器型組件通常是有狀態組件。
tips:受控組件與非受控組件,業務組件,ui組件,
並非 React提供的某種 API,而是使 用 React 的一種模式,用於加強現有組件的功能 簡單來講,一個高階組件就是一個函數,這個函數接受一個組件做爲輸入,而後返回一個新的組件做爲結果,並且,返回的新組件擁有了輸入組件所不具備的功能 。 這裏提到的組件指的並非組件實例,而是一個組件類,也能夠是一個無狀態組件 的函數
import React from ’ react ’ J
function removeUserProp(WrappedComponent) {
return class WrappingComponent extends React.Component {
render() {
const {user, ... otherProps} = this.props;
return <WrappedComponent {... otherProps) />
}
}
export default removeUserProp;
複製代碼
根據返回的新組件和傳人組件參數的關係,高階組件的實現方式能夠分爲兩大類:
上面的 removeUserProp例子就是一個代理方式的高階組件,特色是返回的新組件類 直接繼承自 React.Component類。 新組件扮演的角色是傳入參數組件的一個「代理」,在 新組建的 render 函數中,把被包裹組件渲染出來,除了高階組件本身要作的工做,其他 功能全都轉手給了被包裹的組件 。
function removeUserProp(WrappedComponent) {
return function newRender(props) {
const {user, ... otherProps) = props;
return <WrappedComponent {... otherProps} />
}
}
複製代碼
應用在下列場景中:
操縱 prop;
訪問 ref:(訪問 ref並非值得推薦的 React組件使用方式)
抽取狀態: 其實,咱們已經使用過「抽取狀態」的高階組件了,就是 react-redux 的 connect 函 數,注意 connect 函數自己並非高階組件, connect 函數執行的結果是另 一個函數,這 個函數纔是高階組件 。
包裝組件 。
const styleHOC = (WrappedComponent, style) => {
return class HOCComponent extends React.Component {
render() {
return (
<div style={style}>
<WrappedComponent {... this.props}/>
</div>
}
}
}
複製代碼
class PureComponent extends Component{
shouldComponentUpdate(nextProps,nextState){
const {props,state} = this;
return shallowCompare(nextProps,props) && shallowCompare(nextState,state)
}
}
複製代碼
const modi fyProps HOC = (WrappedComponent) => {
return class NewComponent extends WrappedComponent {
render() {
const elements= super.render() ;
const newStyle = {
color: (elements && elements.type ===’div’)?’red’:’green’
}
const newProps = { ... this.props, style: newStyle};
return React.cloneElement(elements, newProps,elements.props.children);
}
}
}
複製代碼
代理方式更加容易實現和控制,繼承方式的惟一優點是能夠操縱特定組件的生命週期函數。 「優先考慮組合,而後才考慮繼承 。」
const loggedinUser = ’ mock user ’;
class AddUserProp extends React.Component {
render() {
const user = loggedinUser ;
return this.props.children(user);
}
}
AddUserProp.propTypes = {
children: React.PropTypes.func.isRequired
}
複製代碼
這個類的代碼,和被加強組件的惟一聯繫就是 this.props.children,並且 this.props. children是函數類型,在 render 函數中 直接調用 this.props.children 函數 ,參數就是咱們 但願傳遞下去的 user。 使用這個 AddUserProp 的靈活之處在於它沒有對被加強組件有任何 props 要求,只 是傳遞一個參數過去,至於怎麼使用,徹底由做爲子組件的函數決定
mixin
extands