zoukankan      html  css  js  c++  java
  • 温习react文档(v0.17)

    前言:自己当初学习的react的还是0.8.x版本,如今技术日新月异,react已经进化到v17.x版本。很多语法已经跟之前不同,所以重新温习一下

    State 的更新可能是异步的

    出于性能考虑,React 可能会把多个 setState() 调用合并成一个调用。

    因为 this.props 和 this.state 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。

    例如,此代码可能会无法更新计数器:

    // Wrong
    this.setState({
      counter: this.state.counter + this.props.increment,
    });

    要解决这个问题,可以让 setState() 接收一个函数而不是一个对象。这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数:

    // Correct
    this.setState((state, props) => ({
      counter: state.counter + props.increment
    }));

    上面使用了箭头函数,不过使用普通的函数也同样可以

    事件处理

    在 React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault 。例如,传统的 HTML 中阻止链接默认打开一个新页面,你可以这样写:

    <a href="#" onclick="console.log('The link was clicked.'); return false">
      Click me
    </a>

    在 React 中,可能是这样的:

    function ActionLink() {
      function handleClick(e) {    e.preventDefault();    console.log('The link was clicked.');  }
      return (
        <a href="#" onClick={handleClick}>      Click me
        </a>
      );
    }

    在这里,e 是一个合成事件。React 根据 W3C 规范来定义这些合成事件,所以你不需要担心跨浏览器的兼容性问题。React 事件与原生事件不完全相同。如果想了解更多,请查看 SyntheticEvent 参考指南。

    事件中的this

    // 为了在回调中使用 `this`,这个绑定是必不可少的    this.handleClick = this.handleClick.bind(this);

    <button onClick={() => this.handleClick()}>        Click me  </button>

    向事件处理程序传递参数

    在循环中,通常我们会为事件处理函数传递额外的参数。例如,若 id 是你要删除那一行的 ID,以下两种方式都可以向事件处理函数传递参数:

    <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
    <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

    上述两种方式是等价的,分别通过箭头函数和 Function.prototype.bind 来实现。

    在这两种情况下,React 的事件对象 e 会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。

    key

    const todoItems = todos.map((todo, index) =>
      // Only do this if items have no stable IDs  <li key={index}>    {todo.text}
      </li>
    );

    我们不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。可以看看 Robin Pokorny 的深度解析使用索引作为 key 的负面影响这一篇文章。

    https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318

    受控组件

    在 HTML 中,表单元素(如<input>、 <textarea> 和 <select>)通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。

    我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。

    例如:

    this.setState({
      [name]: value});

    等同 ES5:

    var partialState = {};
    partialState[name] = value;this.setState(partialState);

    这里使用了 ES6 计算属性名称的语法更新给定输入名称对应的 state 值:

    组合 vs 继承

    包含关系

    有些组件无法提前知晓它们子组件的具体内容。在 Sidebar(侧边栏)和 Dialog(对话框)等展现通用容器(box)的组件中特别容易遇到这种情况。

    我们建议这些组件使用一个特殊的 children prop 来将他们的子组件传递到渲染结果中:

    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>
      );
    }

    在 CodePen 上尝试

    <FancyBorder> JSX 标签中的所有内容都会作为一个 children prop 传递给 FancyBorder 组件。因为 FancyBorder 将 {props.children} 渲染在一个 <div> 中,被传递的这些子组件最终都会出现在输出结果中。

    少数情况下,你可能需要在一个组件中预留出几个“洞”。这种情况下,我们可以不使用 children,而是自行约定:将所需内容传入 props,并使用相应的 prop。

    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 元素本质就是对象(object),所以你可以把它们当作 props,像其他数据一样传递。这种方法可能使你想起别的库中“槽”(slot)的概念,但在 React 中没有“槽”这一概念的限制,你可以将任何东西作为 props 进行传递。

    特例关系

    有些时候,我们会把一些组件看作是其他组件的特殊实例,比如 WelcomeDialog 可以说是 Dialog 的特殊实例。

    在 React 中,我们也可以通过组合来实现这一点。“特殊”组件可以通过 props 定制并渲染“一般”组件:

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

    在 CodePen 上尝试

    组合也同样适用于以 class 形式定义的组件。

    function Dialog(props) {
      return (
        <FancyBorder color="blue">
          <h1 className="Dialog-title">
            {props.title}
          </h1>
          <p className="Dialog-message">
            {props.message}
          </p>
          {props.children}    </FancyBorder>
      );
    }
    
    class SignUpDialog extends React.Component {
      constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.handleSignUp = this.handleSignUp.bind(this);
        this.state = {login: ''};
      }
    
      render() {
        return (
          <Dialog title="Mars Exploration Program"
                  message="How should we refer to you?">
            <input value={this.state.login}               onChange={this.handleChange} />        <button onClick={this.handleSignUp}>          Sign Me Up!        </button>      </Dialog>
        );
      }
    
      handleChange(e) {
        this.setState({login: e.target.value});
      }
    
      handleSignUp() {
        alert(`Welcome aboard, ${this.state.login}!`);
      }
    }

    在 CodePen 上尝试

    那么继承呢?

    在 Facebook,我们在成百上千个组件中使用 React。我们并没有发现需要使用继承来构建组件层次的情况。

    Props 和组合为你提供了清晰而安全地定制组件外观和行为的灵活方式。注意:组件可以接受任意 props,包括基本数据类型,React 元素以及函数。

    如果你想要在组件间复用非 UI 的功能,我们建议将其提取为一个单独的 JavaScript 模块,如函数、对象或者类。组件可以直接引入(import)而无需通过 extend 继承它们。

     

    批注:这个知识点对我来说,也是新鲜的。

  • 相关阅读:
    ubuntu18 faster-rcnn
    osgViewer应用基础
    error C2086: “int WINGDIAPI”: 重定义
    test5
    test3
    test2
    Kinect关节数据
    MySQL乱码问题以及utf8mb4字符集
    mysql5.7执行sql语句报错:In aggregated query without GROUP BY, expression #1 of SELECT list contains nonagg
    yum安装软件报错:curl#6
  • 原文地址:https://www.cnblogs.com/zccst/p/14798985.html
Copyright © 2011-2022 走看看