• react基础篇四


    列表 & Keys

    渲染多个组件

    你可以通过使用{}在JSX内构建一个元素集合

    下面,我们使用Javascript中的map()方法遍历numbers数组。对数组中的每个元素返回<li>标签,最后我们得到一个数组listItems

    我们把整个listItems插入到ul元素中,然后渲染进DOM:

    ReactDOM.render(
      <ul>{listItems}</ul>,
      document.getElementById('root')
    );
    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        <li key={number.toString()}>
          {number}
        </li>
      );
      return (
        <ul>{listItems}</ul>
      );
    }
    
    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
      <NumberList numbers={numbers} />,
      document.getElementById('root')
    );

    一个元素的key最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用来自数据的id作为元素的key

    如果列表项目的顺序可能会变化,我们不建议使用索引来用作键值,因为这样做会导致性能的负面影响,还可能引起组件状态问题。如果你想要了解更多,请点击深度解析key的必要性。如果你选择不指定显式的键值,那么React将默认使用索引用作为列表项目的键值。

    键(key)只是在兄弟之间必须唯一

    数组元素中使用的key在其兄弟之间应该是独一无二的。然而,它们不需要是全局唯一的。当我们生成两个不同的数组时,我们可以使用相同的键

    function Blog(props) {
      const sidebar = (
        <ul>
          {props.posts.map((post) =>
            <li key={post.id}>
              {post.title}
            </li>
          )}
        </ul>
      );
      const content = props.posts.map((post) =>
        <div key={post.id}>
          <h3>{post.title}</h3>
          <p>{post.content}</p>
        </div>
      );
      return (
        <div>
          {sidebar}
          <hr />
          {content}
        </div>
      );
    }
    
    const posts = [
      {id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
      {id: 2, title: 'Installation', content: 'You can install React from npm.'}
    ];
    ReactDOM.render(
      <Blog posts={posts} />,
      document.getElementById('root')
    );

    key会作为给React的提示,但不会传递给你的组件。如果您的组件中需要使用和key相同的值,请用其他属性名显式传递这个值:

    const content = posts.map((post) =>
      <Post
        key={post.id}
        id={post.id}
        title={post.title} />
    );

    上面例子中,Post组件可以读出props.id,但是不能读出props.key

    表单

    HTML表单元素与React中的其他DOM元素有所不同,因为表单元素生来就保留一些内部状态。例如,下面这个表单只接受一个唯一的name。

    <form>
      <label>
        Name:
        <input type="text" name="name" />
      </label>
      <input type="submit" value="Submit" />
    </form>

    当用户提交表单时,HTML的默认行为会使这个表单跳转到一个新页面。在React中亦是如此。但大多数情况下,我们都会构造一个处理提交表单并可访问用户输入表单数据的函数。实现这一点的标准方法是使用一种称为“受控组件”的技术。

    受控组件

    在HTML当中,像<input>,<textarea>, 和 <select>这类表单元素会维持自身状态,并根据用户输入进行更新。但在React中,可变的状态通常保存在组件的状态属性中,并且只能用 setState() 方法进行更新。

    我们通过使react变成一种单一数据源的状态来结合二者。React负责渲染表单的组件仍然控制用户后续输入时所发生的变化。相应的,其值由React控制的输入表单元素称为“受控组件”。

    例如,我们想要使上个例子中在提交表单时输出name,我们可以写成“受控组件”的形式:

    class NameForm extends React.Component {
      constructor(props) {
        super(props);
        this.state = {value: ''};
    
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }
    
      handleChange(event) {
        this.setState({value: event.target.value});
      }
    
      handleSubmit(event) {
        alert('A name was submitted: ' + this.state.value);
        event.preventDefault();
      }
    
      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              Name:
              <input type="text" value={this.state.value} onChange={this.handleChange} />
            </label>
            <input type="submit" value="Submit" />
          </form>
        );
      }
    }

    在 CodePen 上尝试。

    由于 value 属性是在我们的表单元素上设置的,因此显示的值将始终为 React数据源上this.state.value 的值。由于每次按键都会触发 handleChange 来更新当前React的state,所展示的值也会随着不同用户的输入而更新。

    使用”受控组件”,每个状态的改变都有一个与之相关的处理函数。这样就可以直接修改或验证用户输入。例如,我们如果想限制输入全部是大写字母,我们可以将handleChange 写为如下:

    handleChange(event) {
      this.setState({value: event.target.value.toUpperCase()});

    在React应用中,对应任何可变数据理应只有一个单一“数据源”。通常,状态都是首先添加在需要渲染数据的组件中。然后,如果另一个组件也需要这些数据,你可以将数据提升至离它们最近的共同祖先中。你应该依赖 自上而下的数据流,而不是尝试在不同组件中同步状态。

    组合 vs 继承(即slot)

    包含关系

    一些组件不能提前知道它们的子组件是什么。这对于 Sidebar 或 Dialog 这类通用容器尤其常见。

    我们建议这些组件使用 children 属性将子元素直接传递到输出。

    function FancyBorder(props) {
      return (
        <div className={'FancyBorder FancyBorder-' + props.color}>
          {props.children}
        </div>
      );
    }

    这样做还允许其他组件通过嵌套 JSX 来传递子组件。

    function WelcomeDialog() {
      return (
        <FancyBorder color="blue">
          <h1 className="Dialog-title">
            Welcome
          </h1>
          <p className="Dialog-message">
            Thank you for visiting our spacecraft!
          </p>
        </FancyBorder>
      );
    }

    虽然不太常见,但有时你可能需要在组件中有多个入口,这种情况下你可以使用自己约定的属性而不是 children

    function SplitPane(props) {
      return (
        <div className="SplitPane">
          <div className="SplitPane-left">
            {props.left}
          </div>
          <div className="SplitPane-right">
            {props.right}
          </div>
        </div>
      );
    }
    function App() {
      return (
        <SplitPane
          left={
            <Contacts />
          }
          right={
            <Chat />
          } />
      );
    }

    在 CodePen 上试试。

    类似 <Contacts /> 和 <Chat /> 这样的 React 元素都是对象,所以你可以像任何其他元素一样传递它们。

  • 相关阅读:
    顶目群定义及项目群管理
    项目管理与项目组合管理的不同
    IT项目经理:人际关系技能和领导技能的重要性
    IT 项目经理的职业生涯
    Sharepoint2010 中隐藏 "快速启动"与"最近修改'
    3 个基本的IT项目组合种类
    项目成功的标志及决定因素
    HDL,你们作对了吗?
    JAVA代码编写的30条建议
    八款开源 Android 游戏引擎
  • 原文地址:https://www.cnblogs.com/airfand/p/10674771.html
Copyright © 2020-2023  润新知