筑基-Props任意参及六种使用场景

226 阅读6分钟

react中组件与组件通信用的props,当然还有其他的,context mobx redux 但这里主要介绍props

props接受任意参,并且只读,那到底都可以传接受什么,我们先列出来一一说明

1、基础数据类型
2、this.props.children
3、接收一个html代码片段
(函数返回值)
4、接收一个组件
5、{...obj}
6、子传父 callback形式

ok 正式进入主题

首先看一下场景
很多网站都会有模块标题看代码
<div className="h3">
    <h3>创建项目一</h3>
</div>

<div className="h3">
    <h3>组件</h3>
</div>

<div className="h3">
    <h3>props</h3>
</div>

当前页面可能会出现三到五次,当然也有可能在列表页面同样出来类似的代码
重复写就ok了,开发是开发,不出问题怎么弄都好,现在问题来了
所有的模块标题不可能用h3标签了,是不是你这个项目使用了多少次就要引入多少次那是不是很麻烦,有可能会漏掉了。
早期开发其实大家已有widget的概念了。
也可以简单理解为,我们函数在多次相同使用的情况下是不是有函数封装的概念。
所以我们简单的组件概念就先产生了,能不能只写一份,其他把文字换了就可以了。这样改标签是不是改一份就可以了。

第一种 解决文字适配问题

vi  react/first-react/src/App.js 修改
这个页面后期对于路由开发有很大用途,前期只要照做就可以了

//1引入
import Props from './views/Props';
// 还记得前几前说过吧,文件夹要大写

//2使用
import Home from './views/Home';

import Test from './views/Test';

import Props from './views/Props';

function App() {
  return (
    <div className="App">
        {/*<Home/>
        <Test/>
        <Com/>*/}
        <Props/>
    </div>
  );
}

export default App;

所以App.js 做了两件事
1、引入某个页面
2、使用某个页面
vi src/views/Props/index.jsx

import React, { Component } from 'react';

class View extends Component {
    render(){
        return(
            <div>
                <div className="h3">
                    <h3>创建项目一</h3>
                </div>
                <div className="h3">
                    <h3>组件</h3>
                </div>
                <div className="h3">
                    <h3>props</h3>
                </div>
            </div>
        )
    }
}
export default View;
vi src/views/Props/H3.jsx
import React, { Component } from 'react';
class View extends Component {
    render(){
        return(
            <div className="h3">
               <h3>props</h3>
            </div>
        )
    }
}
export default View;
以上为props为页面代码
H3为一个组件的代码
vi src/views/Props/index.jsx
import React, { Component } from 'react';

import H3 from './H3.jsx';

render(){
    return(
            <div>
                <H3/>
                <div className="h3">
                    <h3>创建项目一</h3>
                </div>
                <div className="h3">
                    <h3>组件</h3>
                </div>
                <div className="h3">
                    <h3>props</h3>
                </div>
                <H3 title="创建项目一"/>
                <H3 title="组件"/>
                <H3 title="props"/>
            </div>
        )
}

<H3/>
这样内容是固定的,但实现标签可以一次修改多次使用
继续改造
增加一个title属性,内容为各模块的标题
<H3 title="创建项目一"/>
<H3 title="组件"/>
<H3 title="props"/>
vi src/views/Props/H3.jsx
render(){
    return(
        <div className="h3">
            <h3>{this.props.title}</h3>
        </div>
    )
}
子组件接通过this.props来获取title的内容从面实现标题文字更改
是不是文字更改的问题就解决了
接下来继续升级
场景换升级了
在副标题中有的模块副标题右侧有个更多,有的没有
总不能再做一个组件吧
往下看

第二种 解决有的内容不一样问题

<div className="h3">
     <h3>标题内容</h3>
     <a href="true">更多</a>
</div>
vi src/views/Props/index.jsx
import React, { Component } from 'react';

import Child from './Child.jsx';

render(){
    return(
            <div>
                <Child title="props">
                    <a href="true">更多</a>
                </Child>
                <Child title="props"/>
            </div>
        )
}
单组件改成闭合组件,并且在里面增加a标签内容
vi src/views/Props/Child.jsx
render(){
    return(
        <div className="h3">
            <h3>{this.props.title}</h3>
            {this.props.children}
        </div>
    )
}
子组件通过this.props.children来直接获取父组件中调用闭合组件内的html代码
这样就满足了有更多和没有更多的使用场景了
使用场景继续升级
比如一个页面有导航有三个页面链接
每一个页面都有左侧导航和右侧内容区。
现在问题来了,三个页面中有两个左侧是一样的,另一个只有部分是不一样的
但点击三个页面切换都是在同一网址下。

第三种 接收一个HTML片段

以上需求,
假定左侧Left 是一个组件

但左侧又分了上中下三部分
上部分是一个基本信息
中间是一个导航区
下部是一个广告位
中间部分目前按上面说的是有两种情况
所以我们给单独提出来
比如是
<ul>
   <li>左侧一</li>
    <li>左侧二</li>
</ul> 
vi src/views/Props/index.jsx
import React, { Component } from 'react';

import Left from './Left.jsx';

render(){
    com(){
        return(
            <ul>
               <li>左侧一</li>
                <li>左侧二</li>
            </ul>
        )
    }
    return(
            <div>
                <header></header>
                <div className="main clearfix">
                    <Left com={this.com}/>
                    <div className="right_con"></div>
                </div>
            </div>
        )
}
使用Left组件接收一个函数,函数返回一个html片段。
这样我们就可以选择性调用html片段了
vi src/views/Props/Left.jsx
import React, { Component } from 'react';
render(){
    return(
            <div>
                <div>top</div>
                {this.props.com()}
                <div>ad</div>
            </div>
        )
}

这样我们就可以在子组件中直接通过this.props.com()
获取某个HTMl 片段了。

问题来了,继续升级
如果左侧ul 内容还有一些其他的功能的情况怎么办可能只是使用一个函数相对来说比较麻烦
这个时候,新方案来了

第四种 接收一个组件

vi src/views/Props/index.jsx
import React, { Component } from 'react';

import Lefts from './Lefts.jsx';
import LeftUl from './LeftUl.jsx';
render(){
    return(
            <div>
                <header></header>
                <div className="main clearfix">
                    <Lefts left={<LeftUl/>}/>
                    <div className="right_con"></div>
                </div>
            </div>
        )
}

left={<LeftUl/>}
可以直接接受一个组件,
接受的这个组件也具备正常组件一件的功能
vi src/views/Props/Left.jsx
import React, { Component } from 'react';
render(){
    return(
            <div>
                <div>top</div>
                {this.props.left}
                <div>ad</div>
            </div>
        )
}

子组件在接受时都是一样的 

LeftUl 就是一个简单的类组件
这样的话,我们组件的使用场景就可以让我们的组件更大的被复用
这就完了吗?
继续

第五种 接收一个{...obj}

第五种其实就是前三种的聚合,除了children由context延伸过来的。
react/first-app/src/views/Props/index.jsx

import React, { Component } from 'react';
import Child from './child.jsx';
import Left from './left.jsx';

class View extends Component{
    com(){
        return(
            <div>
                这是通过函数返回值
            </div>
        )
    }
    render(){
        const obj = {
            title:'prop',
            objCfg:{
            },
            com:this.com,
            left:<Left/>
        }
        return(
            <div>
                <h3>这是关于props的使用</h3>
                <Child {...obj}/>
            </div>
        )
    }
}
export default View;
相当于利用es6的展开运算符,直接把某一项目整个给传下去,
针对多种情况的可以使用这种
子组件可以直接
this.props.title
this.props.com()
this.props.left
第六种 子传父在 后期事件内容章节会讲,这样的我们就整理出了6中使用场景中的五种
1、基础数据类型
2、this.props.children
3、接收一个html代码片段
(函数返回值)
4、接收一个组件
5、{...obj}
6、子传父 callback形式

完整代码如下:
react/first-react/src/App.js

import Home from './views/Home';
import Test from './views/Test';
import Props from './views/Props';

function App() {
  return (
    <div className="App">
        {/*<Home/>
        <Test/>
        <Com/>*/}
        <Props/>
    </div>
  );
}

export default App;

react/first-react/src/views/Props/H3.jsx
// src/views/Props/index.jsx

import React, { Component } from 'react';

class View extends Component {

    render(){
        return(
            <div className="h4">
                <h4>{this.props.title}</h4>
                {this.props.children}
                {/*<a href="true" className="reload">换一换</a>
                <ul>
                    <li>语文</li>
                </ul>*/}
            </div>
        )
    }
}
export default View;

react/first-react/src/views/Props/Child.jsx
// src/views/Props/index.jsx
import React, { Component } from 'react';
class View extends Component {

    render(){
        return(
            <div>
                <h3>第三种使用场景</h3>
                {this.props.com()}
            </div>
        )
    }
}
export default View;
react/first-react/src/views/Props/Left.jsx
import React, { Component } from 'react';
class View extends Component {

    render(){
        return(
            <div>
                <h4>上部分</h4>
                {this.props.left}
                <h5>下部分</h5>
            </div>
        )
    }
}
export default View;
react/first-react/src/views/Props/LeftUl.jsx
import React, { Component } from 'react';
class View extends Component {

    render(){
        return(
            <ul>
                <li>链接一</li>
                <li>链接二</li>
                <li>链接三</li>
                <li>链接四</li>
            </ul>
        )
    }
}
export default View;

react/first-react/src/views/Props/index.jsx
// src/views/Props/index.jsx

import React, { Component } from 'react';

import H3 from './H3.jsx';
import Child from './Child.jsx';

import Left from './Left.jsx';
import Lefts from './Lefts.jsx';
import LeftUl from './LeftUl.jsx';

class View extends Component {

    com(){
        return(
            <div>
                这是com返回的代码片段
            </div>
        )
    }
    render(){
        const obj = {
            title:'第五种使用场景',
            info:{
                name:'小明',
                age:32
            },
            com:this.com,
            left:<LeftUl/>
        }
        return(
            <div>
                <H3 title="创建项目一"/>
                <H3 title="组件"/>
                <H3 title="props"/>

                <Child title="props">
                    <a href="true">更多</a>
                </Child>
                <Child title="props"/>

                <Left com={this.com}/>


                <Lefts left={<LeftUl/>}/>

                <Child {...obj}/>
            </div>
        )
    }
}
export default View;

代码最好是按上面一步步来,有问题了再看整体代码。

ok~