React 元件模式學習總結

李赫feixuan發表於2019-03-21

容器元件(Container)

容器元件是你的資料或邏輯層並利用 stateful API,使用生命週期事件,你可以連線 state 到 redux 或者 Flux 的 storage 中,並將資料和回撥作為 props 傳遞給子元件。

負責與Store互動 

容器元件自身不會觸發action(他只是披在傻瓜元件上的一層殼) 

內:向傻瓜元件傳遞由Store獲得的props 

外:向Store派發使用者操作傻瓜元件引起的action 

父元件

import React, {PureComponent} from "react"
import PropTypes from 'prop-types';
import axios from "axios"
import ProductList from "views/product-list"
class NwdContainer extends React.Component {
    constructor(props){
        super(props)
    }
    state = {
        names: ""
    }
    componentDidMount() {
        var _this = this;
        axios.get('https://api.github.com/search/users?q=tom+repos:%3E42+followers:%3E1000')
            .then(function (res) {
                _this.setState({
                    names: res.data.total_count
                })
            })
    }
    render() {
        return (
            <div>
                <ProductList names={this.state.names}></ProductList>
            </div>
        )
    }
}
export default NwdContainer複製程式碼

子元件(展示元件)

import React, {PureComponent} from "react"
import PropTypes from 'prop-types';
const ProductList = (props) => {
    return (
        <div>
            {props.names}
        </div>
    )
}
export default ProductLis複製程式碼

如上 容器元件,就是負責獲取使用者資料,然後以props的形式傳遞給展示元件ProductList來渲染。容器元件也不會在頁面中渲染出具體的DOM節點,因此,它通常就充當資料來源的角色。目前很多常用的框架,也都採用這種元件形式。如:React Redux的connect(), Relay的createContainer(), Flux Utils的Container.create()等。

展示元件

展示元件 使用 props、render 和 context (無狀態API),並且由於不需要使用生命週期相關 Api,可以使用純函式來簡化編寫函式式元件 
import React, {PureComponent} from "react"
import {PropTypes} from 'prop-types';
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'

const NwdCard = (props) =>{
    console.log(props)
    return (
        <div>{props.name}</div>
    )
}

export default  NwdCard複製程式碼
展示元件 僅從 props 接收資料和回撥,這些資料和回撥可以由其容器元件(父元件)提供

父元件

import React, {PureComponent} from "react"
import {PropTypes} from 'prop-types';
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import NwdCard from "views/nwd-card";
export default class Form extends React.Component {
    constructor(props) {
        super(props)
    }
    state = {
        name: "你我貸1"
    }
    componentDidMount() {
        this.setState(() =>{
            return {
                name:"你我貸2"
            }
        })
    }
    render() {
        return (
            <div>
               <NwdCard name={this.state.name}></NwdCard>
            </div>
        )
    }
}複製程式碼

子元件

import React, {PureComponent} from "react"
import {PropTypes} from 'prop-types';
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'



const NwdCard = (props) =>{
    console.log(props)
    return (
        <div>{props.name}</div>
    )
}

export default  NwdCard複製程式碼

輸出:

React 元件模式學習總結

高階元件

高階元件是一種函式,它接受一個元件作為引數,然後返回一個新的元件

比如說 react-router-dom提供的withRouter就是典型的高階元件,可以先說說withRouter的作用

一般路由元件可以直接訪問當前路由的match,location,history,當一個非路由元件也想訪問到當前路由的match,location,history物件,那麼withRouter將是一個非常好的選擇,可以理解為將一個元件包裹成路由元件。

路由元件:

import React, {PureComponent} from "react"
import PropTypes from 'prop-types';

import TestRouterChild from "views/test-routerchild"

class TestWithRouter extends React.Component {
    constructor(props){
        super(props)
    }
    componentDidMount() {
        console.log("路由元件輸出--------------")
        console.log(this.props)
        console.log(this.props.location.pathname)
    }
    render() {
        return (
            <div>
                你我貸
                <TestRouterChild></TestRouterChild>
            </div>
        )
    }
}
export default TestWithRouter複製程式碼

非路由元件 (子元件):

import React, {PureComponent} from "react"
import PropTypes from 'prop-types';

class TestRouterChild extends React.Component {
    constructor(props){
        super(props)
    }
    handle = () => {
        this.props.history.push("life")
    }
    render() {
        console.log("子路由輸出---------------------")
        console.log(this.props)
        console.log(this.props.location)
        return (
            <div>
                <div>子元件</div>
                <button onClick={this.handle}>click</button>
            </div>
        )
    }
}
export default TestRouterChild複製程式碼

輸出如下 

React 元件模式學習總結

React 元件模式學習總結

通過上圖看出:綠色的是非路由元件中的輸出,紅色的是路由元件的輸出,因此子路由即非路由元件是無法獲取當前路由的引數,點選跳轉也無法跳轉到對應的頁面

引入withRouter

非路由元件(子元件)

import React, {PureComponent} from "react"
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom'

@withRouter
class TestRouterChild extends React.Component {
    constructor(props){
        super(props)
    }
    handle = () => {
        this.props.history.push("life")
    }
    render() {
        console.log("子路由輸出---------------------")
        console.log(this.props)
        console.log(this.props.location)
        return (
            <div>
                <div>子元件</div>
                <button onClick={this.handle}>click</button>
            </div>
        )
    }
}
export default TestRouterChild複製程式碼

輸出如下:

React 元件模式學習總結

React 元件模式學習總結

通過上圖可以觀察到 引入withRouter後 非路由元件(子路由)可以獲取當前的location  history 

如果不用@withRouter  可以使用  export default withRouter(TestRouterChild)


渲染回撥元件(Render Callback)

渲染回撥或渲染屬性(props) 被用於共享或重用元件邏輯,將元件中的渲染邏輯委託給其子元件

父元件

import React, {PureComponent} from "react"
import PropTypes from 'prop-types';
import CallbackChild from "views/callback-child"
class NwdCallback extends React.Component {
    constructor(props){
        super(props)
    }
    render() {
        return (
            <div>
                <CallbackChild>
                    {
                        (msg) => (
                            <div>
                                我的名字叫: {msg}
                            </div>
                        )
                    }
                </CallbackChild>
            </div>
        )
    }
}
export default NwdCallback複製程式碼

子元件

import React, {PureComponent} from "react"
import PropTypes from 'prop-types';
class CallBackChild extends React.Component {
    constructor(props){
        super(props)
    }
    state = {
        name: "飛旋的留戀"
    }
    componentDidMount() {
    }
    render() {
        console.log(this.props)
        console.log(this.props.children)
        return (
            <div>
                {this.props.children(this.state.name)}
            </div>
        )
    }
}
export default CallBackChild複製程式碼

如下

React 元件模式學習總結

React 元件模式學習總結

註釋:雖然前端開發更喜歡使用 高階元件的可重用邏輯,但是使用 渲染回撥 仍然有一些非常好的理由和優勢:渲染回撥減少了名稱空間衝突,並更好的說明了邏輯來源。


相關文章