React中文文档阅读总结——快速入门

快速入门

点击进入——React中文文档


JSX及元素渲染

  1. React 是一个 JavaScript 库

  2. const element = <h1>Hello, world!</h1>; 考虑一下这个变量的声明,它既不是字符串也不是HTML,这就是 JSX ,它是 JavaScrip 的一种扩展语法。我们推荐在 React 中使用这种语法来描述 UI 信息,它具有 JavaScrip 的全部能力,可以生成React “元素”。

  3. 比起 HTML,JSX 更接近于 JavaScript,所以 React DOM 使用驼峰(camelCase)属性命名约定,而不是HTML属性名称。 例如,class 在JSX中变为classNametabindex 变为 tabIndex

  4. 元素(Elements)是 React 应用中最小的构建部件,它是构成组建的“材料”,一个元素用于描述你在将在屏幕上看到的内容,例如:const element = <h1>Hello, world</h1>;

  5. React 元素是 不可突变(immutable) 的,一旦你创建了一个元素, 就不能再修改其子元素或任何属性。一个元素就像电影里的一帧: 它表示在某一特定时间点的 UI 。更新 UI 的唯一方法是创建一个新的元素, 并将其传入ReactDOM.render() 方法。但实际上,大多数 React 应用只会调用 ReactDOM.render() 一次。更新UI更多的是通过与 状态(state)生命周期 挂钩来实现的。

组件(Components) 和 属性(Props)

  1. 组件名称总是以大写字母开始

  2. 组件必须返回一个单独的根元素。

  3. function sum(a, b) { return a + b; },这种函数称为 “ 纯函数 ” ,因为它们不会试图改变它们的输入,并且 对于同样的输入,始终可以得到相同的结果 。 反之, 以下是非纯函数, 因为它改变了自身的输入值: function withdraw(account, amount) { account.total -= amount; }

  4. 所有 React 组件都必须是 纯函数,并禁止修改其自身 props 。

状态(State) 和 生命周期

  1. this.props 由 React 本身设定, 而 this.state 具有特殊的含义,但如果需要存储一些不用于视觉输出的内容,则可以手动向类中添加额外的字段。 如果在 render() 方法中没有被引用, 它不应该出现在 state

  2. 关于 setState() 有三件事是你应该知道的:

  • 不要直接修改 state(状态)

    例如,这样将不会重新渲染一个组件:this.state.comment = 'Hello';

    正确的做法是用 setState() 来修改 statethis.setState({comment: 'Hello'});

  • state(状态) 更新可能是异步的

    React 为了优化性能,有可能会将多个 setState() 调用合并为一次更新。因为 this.propsthis.state 可能是异步更新的,你不能依赖他们的值计算下一个state(状态)。

    例如, 以下代码可能导致 counter(计数器)更新失败:

    // 错误
    this.setState({
      counter: this.state.counter + this.props.increment,
    });
    复制代码

    要弥补这个问题,使用另一种 setState() 的形式,它 接受一个函数而不是一个对象 。这个函数将接收 前一个状态 作为 第一个参数 ,应用 更新时的 props 作为 第二个参数

    // 正确
    this.setState((prevState, props) => ({
      counter: prevState.counter + props.increment
    }));
    复制代码
  • state(状态)更新会被合并

    当你调用 setState() , React 将合并你提供的对象到当前的状态中。

  • 数据向下流动

    如果把组件树想像为 props(属性) 的瀑布,所有组件的 state(状态) 就如同一个额外的水源汇入主流,且只能随着主流的方向向下流动。

    任何 state(状态) 始终由某个特定组件所有,并且从该 state(状态) 导出的任何数据 或 UI 只能影响树中 “下方” 的组件。

处理事件

  1. 通过 React 元素处理事件跟在 DOM 元素上处理事件非常相似。但是有一些语法上的区别:
  • React 事件使用驼峰命名,而不是全部小写。

  • 通过 JSX , 你传递一个函数作为事件处理程序,而不是一个字符串。

  • 在 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>
      );
    }
    复制代码

条件渲染

  1. 在 React 中,你可以创建不同的组件封装你所需要的行为。然后,只渲染它们之中的一些,取决于你的应用的状态。 React 中的条件渲染就和在 JavaScript 中的条件语句一样 。使用 JavaScript 操作符如 if 或者条件操作符来创建渲染当前状态的元素,并且让 React 更新匹配的 UI 。

    虽然声明一个变量并使用一个 if 语句是一个有条件地渲染组件的好方法,有时你可能想要使用一个更简短的语法。在 JSX 中有几种内联条件的方法,如下所述。

    • 使用逻辑 && 操作符的内联 if 用法

      例如当数组arr不为空时渲染组件 <ShowMessages> ,可以写成

      { 
          arr.length>0 &&
          <ShowMessages>
      }
      复制代码

      它可以正常运行,因为在 JavaScript 中, true && expression 总是会评估为 expression ,而 false && expression 总是执行为 false 。 因此,如果条件为 true ,则 && 后面的元素将显示在输出中。 如果是 false,React 将会忽略并跳过它

    • 使用条件操作符的内联 If-Else

      另一个用于条件渲染元素的内联方法是使用 JavaScript 的条件操作符 If-Else 或者是三目运算符 condition ? true : false

    还要记住,无论何时何地,当条件变得太复杂时,可能是提取组件的好时机

  2. 防止组件渲染

    在极少数情况下,您可能希望组件隐藏自身,即使它是由另一个组件渲染的。为此,返回 null 而不使其渲染输出

    例如在如下代码中:

    //方法一:
    function WarningBanner(props) {
      if (!props.warn) {
        return null;
      }
      return (
        <div className="warning">
          Warning!
        </div>
      );
    }
    
    class Page extends React.Component {
      constructor(props) {
        super(props);
        this.state = {showWarning: true}
        this.handleToggleClick = this.handleToggleClick.bind(this);
      }
    
      handleToggleClick() {
        this.setState(prevState => ({
          showWarning: !prevState.showWarning
        }));
      }
      
      render() {
        return (
          <div>
            <WarningBanner warn={this.state.showWarning} />
            <button onClick={this.handleToggleClick}>
              {this.state.showWarning ? 'Hide' : 'Show'}
            </button>
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <Page />,
      document.getElementById('root')
    );
    复制代码

    Hide按钮可以控制 Warning div 的显示隐藏。 同样,以下代码也能达到相同效果:

    //方法二:
    class Page extends React.Component {
      constructor(props) {
        super(props);
        this.state = {showWarning: true}
        this.handleToggleClick = this.handleToggleClick.bind(this);
      }
    
      handleToggleClick() {
        this.setState(prevState => ({
          showWarning: !prevState.showWarning
        }));
      }
      
      render() {
        return (
          <div>
            <div className="warning" style={{display:this.state.showWarning?'':'none'}}>
              Warning!
            </div>
            <button onClick={this.handleToggleClick}>
              {this.state.showWarning ? 'Hide' : 'Show'}
            </button>
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <Page />,
      document.getElementById('root')
    );
    复制代码

    这里没有把 Warning div 当做组件抽离出来,虽然也能达到相同的效果,但是使用 display 只是控制了 Warning div 的显示隐藏,不论如何,Warning div 其实都已经在页面加载了,消耗了资源;而第一种方法返回 null ,却是完完全全的控制了 Warning div 的加载,性能上更胜一筹。

    PS:从组件的 render 方法返回 null 不会影响组件生命周期方法的触发。 例如, componentWillUpdatecomponentDidUpdate 仍将被调用。

列表(Lists) 和 键(Keys)

  1. 首先,先来看一段代码:

    const numbers = [1, 2, 3, 4, 5];
    const listItems = numbers.map((numbers) =>
      <li>{numbers}</li>
    );
    
    ReactDOM.render(
      <ul>{listItems}</ul>,
      document.getElementById('root')
    );
    复制代码

    这段代码显示从 1 到 5 的数字列表。

    当运行上述代码时,虽然会正确显示出列表,但是会收到一个警告:a key should be provided for list items(应该为列表元素提供一个键)。当创建元素列表时,“key” 是一个你需要包含的特殊字符串属性。 键(Keys) 帮助 React 标识哪个项被修改、添加或者移除了 。数组中的 每一个元素 都应该有一个 唯一不变 的键(Keys)来标识。挑选 key 最好的方式是使用一个在它的同辈元素中不重复的标识字符串。多数情况你可以使用数据中的 ID 作为 keys;当要渲染的列表项中没有稳定的 IDs 时,你可以使用数据项的索引值作为 key 的最后选择,例如:

    const numbers = [1, 2, 3, 4, 5];
    const listItems = numbers.map((numbers,index) =>
      <li key={index}>{numbers}</li>
    );
    
    ReactDOM.render(
      <ul>{listItems}</ul>,
      document.getElementById('root')
    );
    复制代码
  2. 使用 keys 提取组件 keys 只在数组的上下文中存在意义。例如,如果你提取 一个 ListItem 组件,应该把 key 放置在数组处理的 <ListItem /> 元素中,不能放在 ListItem 组件自身中的 <li> 根元素上。

    例如:

    function ListItem(props) {
      const value = props.value;
      return (
        // 错误!不需要在这里指定 key:
        <li key={value.toString()}>
          {value}
        </li>
      );
    }
    
    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        // 错误!key 应该在这里指定:
        <ListItem value={number} />
      );
      return (
        <ul>
          {listItems}
        </ul>
      );
    }
    
    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
      <NumberList numbers={numbers} />,
      document.getElementById('root')
    );
    复制代码

    一个好的经验准则是:元素中调用 map() 需要 keys

  3. keys同辈元素中必须是唯一

    在数组中使用的 keys 必须在它们的同辈之间唯一。然而它们并不需要全局唯一。我们可以在操作两个不同数组的时候使用相同的 keys。

表单(Forms)

  1. 受控组件(Controlled Components)

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

    我们可以通过使 React 的 state 成为 “单一数据源原则” 来结合这两个形式。然后渲染表单的 React 组件也可以控制在用户输入之后的行为。这种形式,其 值由 React 控制的输入表单元素 称为“ 受控组件 ”。

    例如,如果我们想在提交时记录名称,我们可以将表单写为受控组件:

    class NameForm extends React.Component {
      constructor(props) {
        super(props);
        this.state = {value: ''};
      }
    
      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.bind(this)}>
            <label>
              Name:
              <input type="text" value={this.state.value} onChange={this.handleChange.bind(this)} />
            </label>
            <input type="submit" value="Submit" />
          </form>
        );
      }
    }
    
    ReactDOM.render(
      <NameForm />,
      document.getElementById('root')
    );
    复制代码

    设置表单元素的value属性之后,其显示值将由 this.state.value 决定,以满足React状态的同一数据理念。每次键盘敲击之后会执行 handleChange 方法以更新React状态,显示值也将随着用户的输入改变。

    由于 value 属性设置在我们的表单元素上,显示的值总是 this.state.value,以满足 state 状态的同一数据理念。由于 handleChange 在每次敲击键盘时运行,以更新 React state(状态),显示的值将更新为用户的输入。

    对于受控组件来说,每一次 state(状态) 变化都会伴有相关联的处理函数。这使得可以直接修改或验证用户的输入。

  2. 处理多个输入元素

    当您需要处理多个受控的 input 元素时,您可以为每个元素添加一个 name 属性,并且让处理函数根据 event.target.name 的值来选择要做什么。而不必写多个 onChange 函数

    例如:

    class Reservation extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          isGoing: true,
          numberOfGuests: 2
        };
    
        this.handleInputChange = this.handleInputChange.bind(this);
      }
    
      handleInputChange(event) {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;
    
        this.setState({
          [name]: value
        });
      }
    
      render() {
        return (
          <form>
            <label>
              Is going:
              <input
                name="isGoing"
                type="checkbox"
                checked={this.state.isGoing}
                onChange={this.handleInputChange} />
            </label>
            
            <label>
              Number of guests:
              <input
                name="numberOfGuests"
                type="number"
                value={this.state.numberOfGuests}
                onChange={this.handleInputChange} />
            </label>
          </form>
        );
      }
    }
    
    ReactDOM.render(
      <Reservation />,
      document.getElementById('root')
    );
    复制代码

    handleInputChange() 方法中,注意我们如何使用ES6计算的属性名称语法来更新与给定输入名称相对应的 state(状态) 键:

    const name = target.name;
    
    this.setState({
      [name]: value
    });
    复制代码

状态提升(Lifting State Up)

  1. 在一个 React 应用中,对于任何可变的数据都应该循序“单一数据源”原则。通常情况下,state 首先被添加到需要它进行渲染的组件。然后,如果其它的组件也需要它,你可以提升状态到它们最近的祖先组件。你应该依赖 从上到下的数据流向 ,而不是试图在不同的组件中同步状态。

    提升状态相对于双向绑定方法需要写更多的“模板”代码,但是有一个好处,它可以更方便的找到和隔离 bugs。由于任何 state(状态) 都 “存活” 在若干的组件中,而且可以分别对其独立修改,所以发生错误的可能大大减少。另外,你可以实现任何定制的逻辑来拒绝或者转换用户输入。

    如果某个东西可以从 props(属性) 或者 state(状态) 得到,那么它可能不应该在 state(状态) 中。

    状态提升:子组件要渲染的数据不定义在自身 state 中,而是定义在最近的公共父组件中。该数据由父组件通过 props 传递给子组件。当子组件发生改变时,触发父组件的 onChange() 方法,父组件更改 state ,引起子组件数据改变,从而达到A子组件数据变化时B子组件数据跟着变化的效果。)

组合 VS 继承(Composition vs Inheritance)

  1. 如果要在组件之间重用非 U I功能,我们建议将其提取到单独的 JavaScript 模块中。组件可以导入它并使用该函数,对象或类,而不扩展它。

React 的编程思想

  1. 如何拆分组件呢?

    其实只需要像拆分一个新方法或新对象一样的方式即可。一个常用的技巧是 单一职责原则 ,即一个组件理想情况下只处理一件事。如果一个组件持续膨胀,就应该将其拆分为多个更小的组件中。


写在最后:强烈建议自己读一遍 React中文文档 (有些翻译错误,不影响阅读,有能力可以去读原版。 O(∩_∩)O哈哈~)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值