React

React组件化(二)高阶组件、装饰器、复合组件

2019-10-30  本文已影响0人  key君
高阶组件

定义:是一个函数,它接收一个组件并返回另一个组件
基本使用

import React, { Component } from 'react'
//基础组件
function Child(props){
    return <div className="border">Child</div>;
}
//传入一个组件 返回一个组件
const foo = (Cmp) => {
    //可能带参数 返回props
    return (props) => {
        return <Cmp {...props}/>;
    }
}

export default class HocPage extends Component {
    render() {
        const Foo = foo(Child);
        return (
            <div>
                <Foo/>
            </div>
        )
    }
}

装饰器
import React, { Component } from 'react'

// function Child(props){
//     // console.log(props);
    
//     return <div className="border">Child</div>;
// }
//返回组件
// const foo = (Cmp) => {
//     //可能带参数 返回props
//     return (props) => {
//         return <Cmp {...props}/>;
//     }
// }



const foo = Cmp => props => {
    return (
        <div className="border">
            <Cmp {...props}/>
        </div>
    )
}

//装饰器 不支持function 可以多层嵌套
@foo
@foo
class ChildSceond extends Component{
    render(){
        return <div className="border">Child</div>
    }
}

export default class HocPage extends Component {
    render() {
        // console.log(this.props);
        // const Foo = foo(Child);
        return (
            <div>
                {/* <Foo/> */}
                <ChildSceond/>
            </div>
        )
    }
}

先安装

git add .
git commit -m 'up'
yarn eject

配置package.json

"babel": { "presets": [
  "react-app"
  ], "plugins": [
  [
  "@babel/plugin-proposal-decorators", {
  "legacy": true }
  ] ]
  }

安装装饰器器插件

npm install @babel/plugin-proposal-decorators --save-dev

yarn add @babel/plugin-proposal-decorators --dev

然后启动 如果报错 删除node_modules 再yarn install一下再启动

npm start

有警告的话在根目录创建jsconfig.json

{
    "compilerOptions": {
      "experimentalDecorators": true
    }
  }
组件复合 具名插槽与不具名插槽

components/Layout.js

import React, { Component } from 'react'
import TopBar from './TopBar';

export default class Layout extends Component {
    componentDidMount(){
        const {title} = this.props;
        document.title = title;
    }
    render() {
        const {children,showTopBar} = this.props;
        const a = [];
        if(children.$$typeof){
            //不具名 直接是节点
            a.push(children);
        }else{
            //具名是个对象
            for (let item in children) {
                //对象里面的value是节点
                a.push(children[item]);
            }
        }
        
        return (
            <div>
                {
                    showTopBar && <TopBar/>
                }
                {/* {children.btn}
                {children.txt} */}
                {
                    //可以适应具名插槽或不具名插槽 但是不能一起混着来
                    a.map((item,index) => {
                        return <React.Fragment key={index}>{item}</React.Fragment>
                    })
                }
            </div>
        )
    }
}

components/TopBar.js

import React, { Component } from 'react'
import { handleComsumer } from '../AppContext'

//高阶函数
// const handleComsumer = Cmp => props => {
//     return <Consumer>{ctx => <Cmp {...ctx} {...props}/>}</Consumer>;
// }

export default class TopBar extends Component {
    render() {
        const Top = handleComsumer(TopBarHandle);
        return (
            <Top/>
            // <Consumer>
            //     {
            //         ctx => <TopBarHandle {...ctx}/>
            //     }
            // </Consumer>
        )
    }
}

function TopBarHandle(props){
    return (<div className="topBar">
        {props.user.name}
    </div>)
}

pages/UserPage.js

import React, { Component } from 'react'
import TopBar from '../components/TopBar'
import Layout from '../components/Layout'

export default class UserPage extends Component {
    render() {
        return (
            <Layout showTopBar={true} title="用户中心">
                {/* <div>
                    <h1>UserPage</h1>
                </div> */}
                {
                    {
                        btn: <button>按钮</button>,
                        txt: '文案'
                    }
                }
            </Layout>
        )
    }
}

上一篇 下一篇

猜你喜欢

热点阅读