【React】组件 & Props

文章目录

组件允许将UI拆分为独立可复用的代码片段,并对每个片段进行独立构思。
组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。

函数组件与class组件

JavaScript定义组件

function Welcome(props) {
	return <h1>Hello, {props.name}</h1>
}

该函数是一个有效的 React 组件,因为它接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。这类组件被称为“函数组件”,因为它本质上就是 JavaScript 函数。

使用ES6的class来定义组件

class Welcom extends React.Component {
	render() {
		return <h1>Hello, {this.props.name} </h1>;
	}
}

渲染组件

React元素不止可以是DOM标签,也可以是用户自定义的组件。

const element = <Welcome name="Sara"/>

当React元素为用户自定义组件时,它会将JSX所接收的属性以及子组件转换为单个对象传递给组件,这个对象被称之为“props”

例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
    function Welcome(props) {
        return <h1>Hello, {props.name}</h1>;
    }

    const element = <Welcome name="Sara"/>;
    ReactDOM.render(
        element,
        document.getElementById('root')
    );
</script>
</body>
</html>

在这个例子中:

  1. 调用ReactDOM.render()函数,并传入<Welcome name="Sara"/>作为参数。
  2. React调用Welcome组件,并将{name:'Sara'}作为props传入。
  3. Welcome组件将<h1>Hello, Sara</h1>元素作为返回值。
  4. React DOM 将DOM高效地更新为<h1>Hello, Sara</h1>

注意:组件名称必须以大写字母开头
React会将以小写字母开头的组件视为原生DOM标签。

组合组件

组件可以在其输出中引用其他组件。
例如:创建一个可以多次渲染Welcome组件的App组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
    function Welcome(props) {
        return <h1>Hello, {props.name}</h1>;
    }

    function App() {
        return (
            <div>
                <Welcome name="Sara"/>
                <Welcome name="Cahal"/>
                <Welcome name="Edite"/>
            </div>
        );
    }

    ReactDOM.render(
        <App/>,
        document.getElementById('root')
    );
</script>
</body>
</html>

提取组件


    function Comment(props) {
        return (
            <div className="Comment">
                <div className="UserInfo">
                    <img className="Avatar"
                         src={props.author.avatarUrl}
                         alt={props.author.name}
                    />
                    <div className="UserInfo-name">
                        {props.author.name}
                    </div>
                </div>

                <div className="Comment-text">
                    {props.text}
                </div>
                <div className="Comment-date">
                    {formatDate(props.date)}
                </div>
            </div>
        );

该组件用于描述一个社交媒体网站上的评论功能,它接收 author(对象),text (字符串)以及 date(日期)作为 props。

该组件由于嵌套的关系,变得难以维护,且很难复用它的各个部分。因此,让我们从中提取一些组件出来。

首先,我们将提取 Avatar 组件:

    function Avatar(props) {
        return (
            <img className="Avatar"
                 src={props.user.avatarUrl}
                 alt={props.user.name}
            />
        );
    }

Avatar 不需知道它在 Comment 组件内部是如何渲染的。因此,我们给它的 props 起了一个更通用的名字:user,而不是 author

我们建议从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。

我们现在针对 Comment 做些微小调整:

    function Comment(props) {
        return (
            <div className="Comment">
                <div className="UserInfo">
                    <Avatar user={props.author}/>
                    <div className="UserInfo-name">
                        {props.author.name}
                    </div>
                </div>

                <div className="Comment-text">
                    {props.text}
                </div>
                <div className="Comment-date">
                    {formatDate(props.date)}
                </div>
            </div>
        );
    }

接下来,我们将提取 UserInfo 组件,该组件在用户名旁渲染 Avatar 组件:

    function UserInfo() {
        return (
            <div className="UserInfo">
                <Avatar user={props.user}/>
                <div className="UserInfo-name">
                    {props.author.name}
                </div>
            </div>
        );
    }

进一步简化 Comment 组件:

    function Comment(props) {
        return (
            <div className="Comment">
                <UserInfo user={props.author}/>
                <div className="Comment-text">
                    {props.text}
                </div>
                <div className="Comment-date">
                    {formatDate(props.date)}
                </div>
            </div>
        );
    }

最初看上去,提取组件可能是一件繁重的工作,但是,在大型应用中,构建可复用组件库是完全值得的。根据经验来看,如果 UI 中有一部分被多次使用(ButtonPanelAvatar),或者组件本身就足够复杂(AppFeedStoryComment),那么它就是一个可复用组件的候选项。

Props的只读性

组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props。来看下这个 sum 函数:

function sum(a, b) {
  return a + b;
}

这样的函数被称为“纯函数”,因为该函数不会尝试更改入参,且多次调用下相同的入参始终返回相同的结果。

相反,下面这个函数则不是纯函数,因为它更改了自己的入参:

function withdraw(account, amount) {
  account.total -= amount;
}

React 非常灵活,但它也有一个严格的规则:

所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。

当然,应用程序的 UI 是动态的,并会伴随着时间的推移而变化。在下一章节中,我们将介绍一种新的概念,称之为 “state”。在不违反上述规则的情况下,state 允许 React 组件随用户操作、网络响应或者其他变化而动态更改输出内容。

上一篇:<转>jmeter(十三)常见问题及解决方法


下一篇:vue3的h函数