【笔记系列】对 React component 和 props.children 的理解

99 阅读2分钟

React

是一个声明式,高效且灵活的拥有构建用户界面的 JS 库。主要书写的是 JS 代码,利用了 JSX 来实现模板,可以看作是插入到 JS 中的 Markdown Language

组件

React 会将一些简短、独立的代码片段组合成复杂的 UI 界面。

组件类型

class Shop extends React.Component {
    render() {
        return (
            <div className="shopping-list">
                <h1> shopping list for {this.props.name} </h1>
                <ul>
                    <li>Instagram</li>
                    <li>WhatsApp</li>
                </ul>
            </div>
        );
    }
}
// 用法:<Shop name="mark" />

其中,Shop 是一个 React 组件类,或者说是一个 React 组件类型。一个组件接受一些参数,我们把这些参数叫做 props。然后通过 render 方法返回需要显示在屏幕上的视图的层次结构。

render 方法返回值:一个 React 元素,描述了屏幕上需要显示的内容。

JSX 的目的就是为了减轻我们写模板的工作,它做的实际上是:将 <div> 编译成 React.createElement('div')

从原理上看 JSX:

<div className="shopping-list">
  <h1>Shopping List for {props.name}</h1>
  <ul>
    <li>Instagram</li>
    <li>WhatsApp</li>
    <li>Oculus</li>
  </ul>
</div>;

实际上等于

/*#__PURE__*/
React.createElement("div", {
  className: "shopping-list"
}, 
    /*#__PURE__*/React.createElement("h1", null, "Shopping List for ", props.name), 
    /*#__PURE__*/React.createElement("ul", null, 
        /*#__PURE__*/React.createElement("li", null, "Instagram"), 
        /*#__PURE__*/React.createElement("li", null, "WhatsApp"), 
        /*#__PURE__*/React.createElement("li", null, "Oculus")
    )
);

JSX 可以任意使用 JS 语句,只需要用大括号将该表达式包起来。

  • 前文中的 Shop 组件中只渲染了一些内置的 DOM 组件,如 divli 等。但是我们也可以组合和渲染自定义的 React 组件,从而我们可以通过组合不同的 React 组件来实现复杂的 UI 界面。

  • React 元素被看作是 JS 中的一等公民中的对象(first-class JS object),因此我们可以将 React 元素作为参数来进行传递。

  • 在 React 中,我们也可以用 React 元素的数组 来渲染多个元素。

React 中的 props.children

有点类似插槽的感觉,不过这时候的插槽变成了夹心饼干。

假设有一个 Foo 的大组件,以及两个 BazBar 小组件。

const Foo = props => (
  <div>
    <p>I'm {Foo.name}</p>
    <p>abc is: {props.abc}</p>

    <p>I have {props.children.length} children.</p>
    <p>They are: {props.children}.</p>
    <p>{Array.isArray(props.children) ? 'My kids are an array.' : ''}</p>
  </div>
);

const Baz = () => <span>{Baz.name} and</span>;
const Bar = () => <span> {Bar.name}</span>;

在使用(render/call/invoke) Foo 组件的时候,夹入了两个小组件,这两个小组件就是 Foo 大组件中的 props.children 了。

<Foo abc={123}>
  <Baz />
  <Bar />
</Foo>

输出为:

I'm Foo
abc is: 123
I have 2 children.
They are: Baz and Bar
My kids are an array.