美文网首页
React 拾遗:类作为组件 (1)

React 拾遗:类作为组件 (1)

作者: Tim_Lee | 来源:发表于2017-12-06 10:39 被阅读0次

    如何使用代码

    安装项目前置依赖,以及启动项目的方法,参看:React 拾遗:项目脚手架

    请根据文章内容,把相应部分的代码注释取消,即可运行。

    摘要

    本文介绍

    • JavaScript 类与面向对象的参考资料
    • React 类中的属性与方法
    • React 的状态 state 读取与修改

    项目代码地址:React 拾遗:类作为组件 (1)

    JavaScript 类与面向对象

    面向对象编程(Object-Oriented Programming, OOP)是一个古老的概念。OOP 要解决的一个问题是:

    • 需要有一个容器,可以存放属性与方法
    • 容器可以被继承。被继承的容器,其属性与方法都可以在新容器中继续复用

    不管是 C++ 还是 Java 提到的类与实例,或者 Python 的 Metaclass,亦或是 JavaScript 的原型及其扩展,都是为了解决上述面向对象要解决的问题。

    关于 JavaScript 的面向对象与原型链,可以在以下内容中找到详细叙述,本文不再赘述。

    React 中的类组件

    1 最简单的 React 类组件

    React 的最简单的类组件如下所示:

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    
    class App extends Component {
      render() {
        return (
          <div>
            <h1>Title - main title</h1>
            <p>The content part</p>
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    
    • React 的类组件都是继承自 React.Component,其中 Component 可以单独引入
    • React 类组件中唯一必须的方法是 render() {}。该方法返回一段 JSX 代码。
    • 市面上有些教程,仍然使用 createReactClass。由于 React 已经全面转向使用 ES 6,所以用 createReactClass 创建类组件已经不再推荐。建议直接继承 React.Component 来创建 React 类组件。

    2 类组件的属性与状态(state)

    (1) render() 方法中的变量

    为了动态显示 JSX 内容,在 render() 方法中可以使用变量,如下所示:

    class App extends Component {
      render() {
        const title = 'main title';
        return (
          <div>
            <h1>Title - {title}</h1>
            <p>The content part</p>
          </div>
        );
      }
    }
    

    但是 render() 方法中的变量,通常有两种用途:

    • 设置内联样式
    • 临时变量。主要根据条件,返回不同的 JSX 代码,达到根据条件判断而渲染的效果。

    (2) constructor() 中的变量

    如果要设置一个变量,让类中所有方法都能使用,就是放在构造器 constructor() 中。构造器中的变量,在类创建时就同时创建完成,可以在整个类中使用。

    class App extends Component {
      constructor() {
        super()
        this.title = 'title in constructor'
      }
    
      render() {
        return (
          <div>
            <h1>Title - {this.title}</h1>
            <p>The content part</p>
          </div>
        );
      }
    }
    

    两个注意点:

    • 构造器 constructor() 中,需要用一个 super() 方法,继承所有父类的属性与方法。而且,如果这个类组件要接受上层传递下来的 props 时,需要写成
    class App extends Component {
      constructor(props) {
        super(props)
        //...
      }
      //...
    }
    
    • 另外,作为类属性,在constructor()定义和JSX使用时,前面都要加上 this.

    (3) React 类组件的状态

    React 类组件一个非常重要的内容,就是维护自己的内部状态(state)。这个状态需要放在 constructor() 中。类中的重要属性(需要保持的数据),基本都是放在状态中。

    • 注意 state 必须是一个对象。
    • state 中数据的读取,直接使用 this.state.<variable_name>,比如 this.state.title等。
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          title: 'title in constructor',
          person: {
            name: 'Jim',
            age: 25,
            location: 'China'
          }
        };
      }
    
      render() {
        return (
          <div>
            <h1>Title - {this.state.title}</h1>
            <p>The content part</p>
            <ul>
              <li>Name: {this.state.person.jim}</li>
              <li>Age: {this.state.person.age}</li>
              <li>Location: {this.state.person.location}</li>
            </ul>
          </div>
        );
      }
    }
    

    类中状态的修改

    1 使用 .setState() 修改 state

    首先,** 永远不要直接修改 state **。请一定使用.setState() 修改 state 。

    下面实现的功能是,有一个新增加的按钮,点击以后,标题会从 'title in constructor' 更改成 'The changed title'。constructor()中、新方法、JSX中处理都有变化,后面会讲解。

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    
    class App extends Component {
      constructor(props) {
        super(props);
        this.changeNameHandler = this.changeNameHandler.bind(this);
        this.state = {
          title: 'title in constructor',
          person: {
            name: 'Jim',
            age: 25,
            location: 'China'
          }
        };
      }
    
      changeNameHandler() {
        this.setState({ title: 'The changed title' })
      }
    
      render() {
        return (
          <div>
            <h1>Title - {this.state.title}</h1>
            <p>The content part</p>
            <ul>
              <li>Name: {this.state.person.jim}</li>
              <li>Age: {this.state.person.age}</li>
              <li>Location: {this.state.person.location}</li>
            </ul>
            <button onClick={this.changeNameHandler}>Change title</button>
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    

    (1) 修改 state 的方法

    • 类中新增加了一个方法 changeNameHandler,形式是 <className>() {}。该方法只有一个功能,就是修改 state。

    • 该方法调用了 React 类组件自带的方法 this.setState() 方法去修改 state。

    • .setState() 方法接受一个对象,这里传入的对象是 { title: 'The changed title' }。该对象会把 state 中对应的,相同键名的内容进行变更。比如,新的内容 title: 'The changed title' 会覆盖掉原来 state 中是 title: 'title in constructor'。同时 state 中其它部分内容不会受影响,比如 person 那个键名就不会改变且依然存在。

      changeNameHandler() {
        this.setState({ title: 'The changed title' })
      }
    

    (2) 方法绑定 this

    在 constructor() 中,使用了 .bind(this)把该方法绑定在 this 上,这是因为 ES6 中,类方法并没有绑定在 this 上。后面可以使用 babel 插件,使用可以绑定 this 的方法。如果不需要在类中其他地方调用,可以不实用 .bind(this),比如生命周期的那些方法 componentDidMount() 等。

      constructor(props) {
        this.changeNameHandler = this.changeNameHandler.bind(this);
      }
    

    当然可以把绑定 this 放在 JSX 中去做,比如:

            <button onClick={this.changeNameHandler.bind(this)}>Change title</button>
    

    但是建议集中在 constructor 中管理,避免过于分散的 .bind(this) 散落在代码中。

    (3) JSX 中调用方法

    • button 按钮上有一个 onClick 事件调用刚才设置的类方法。当点击按钮时,方法被调用。
    • onClick 中间驼峰大写,区分于 DOM 操作的 onclick
    • 方法的调用要用 {}括号,且使用 this.
      render() {
        return (
          <div>
            {/*... */}
            <button onClick={this.changeNameHandler}>Change title</button>
          </div>
        );
      }
    

    相关文章

      网友评论

          本文标题:React 拾遗:类作为组件 (1)

          本文链接:https://www.haomeiwen.com/subject/wwdkixtx.html