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

如何使用代码

安装项目前置依赖,以及启动项目的方法,参看: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>
    );
  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • 本笔记基于React官方文档,当前React版本号为15.4.0。 1. 安装 1.1 尝试 开始之前可以先去co...
    Awey阅读 7,619评论 14 128
  • GUIDS 第一章 为什么使用React? React 一个提供了用户接口的JavaScript库。 诞生于Fac...
    jplyue阅读 3,495评论 1 11
  • 以下内容是我在学习和研究React时,对React的特性、重点和注意事项的提取、精练和总结,可以做为React特性...
    科研者阅读 8,195评论 2 21
  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,026评论 2 35
  • 【推荐书名】:《只要快乐不要哭泣,可以吗?》 【适合月龄】:3-7岁亲子共读 【推荐理由】:生命教育的收获正是在孩...
    吉熊熊阅读 329评论 0 0