容器元件(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-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複製程式碼
輸出如下
通過上圖看出:綠色的是非路由元件中的輸出,紅色的是路由元件的輸出,因此子路由即非路由元件是無法獲取當前路由的引數,點選跳轉也無法跳轉到對應的頁面
引入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複製程式碼
輸出如下:
通過上圖可以觀察到 引入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複製程式碼
如下
註釋:雖然前端開發更喜歡使用 高階元件的可重用邏輯,但是使用 渲染回撥 仍然有一些非常好的理由和優勢:渲染回撥減少了名稱空間衝突,並更好的說明了邏輯來源。