React Object实现React对象

简介: 最快最便捷的方式是用ES6的class或一个方法来定义一个React组件,但是实际上所有的组件最终都会被转译成一个Object对象,本文将介绍React对象的创建方式和组成结构。

不使用ES6

通常情况下,定义一个React组件可以使用ES6规范中的class关键字:

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

如果不使用ES6语法,可以直接使用 React.createClass 来实现相同的功能:

var Greeting = React.createClass({
  render: function() {
    return <h1>Hello, {this.props.name}</h1>;
  }
});

声明Prop的检查类型以及默认Props值

在前面的博文(React prop类型检查与Dom)中介绍了如何规约Prop的参数值,给出的例子都是用ES6实现的:

class Greeting extends React.Component {
  // ...
}

Greeting.propTypes = {
  name: React.PropTypes.string
};

Greeting.defaultProps = {
  name: 'Mary'
};

在使用 React.createClass 时,可以通过设定传入的对象的一个属性值—— propTypes 来指定参数类型,通过 getDefaultProps() 方法来设定每个参数的默认值:

var Greeting = React.createClass({
  propTypes: {
    name: PropTypes.string
  },

  getDefaultProps: function() {
    return {
      name: 'Mary'
    };
  },

  // ...

});

设定初始化状态

在ES6的 class 结构中,我们可以在构造函数中设定初始化状态:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  // ...
}

在使用 React.createClass 时,可以为传入的对象参数添加一个  getInitialState 方法并返回一个初始状态值:

var Counter = React.createClass({
  getInitialState: function() {
    return {count: this.props.initialCount};
  },
  // ...
});

自动绑定

当使用ES6的 class 关键字声明一个React组件时,类中的方法遵循与常规的方法一样的定义。这就意味着在类中申明的方法在执行时并不会自动属于当前实例,必须在构造函数中显示的使用.bind(this)方法绑定到当前实例:

class SayHello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: 'Hello!'};
    // 必须,否在在handleClick中this将指向调用对象
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    alert(this.state.message);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
}

在使用 React.createClass 时不必绑定所有的方法:

var SayHello = React.createClass({
  getInitialState: function() {
    return {message: 'Hello!'};
  },

  handleClick: function() {
    alert(this.state.message);
  },

  render: function() {
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
});

以上的特性意味着使用ES6编写代码每一个方法都会额外增加一些样板式代码,但是对于大型应用来说代码结构更清晰。

如果十分排斥样板式代码,可以启用Babal的 类属性功能( Class Properties ),利用双箭头来创建方法:

class SayHello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: 'Hello!'};
  }

  handleClick = () => {
    alert(this.state.message);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
}

需要注意的是,目前这个功能还是实验性的,双箭头的表达式很有可能会调整。该提议不一定会被委员会接纳。

如果非常想要尝试这种写法,你可以有这几种实现方式:

  1. 在构造函数中绑定方法。
  2. 使用箭头来定义方法。
  3. 使用 React.createClass 。

代码混合器

注意:

ES6在目前的方案中并不支持代码混合功能,因此在使用ES6编写React代码时并不能实现相关功能。

官方也收到许多在使用混合器时遇到的问题,强烈建议不要在新的代码中使用混合器功能。

以下的内容仅供参考。

某些时候2个不同的组件需要共享一些相同的方法或者功能。这种情况我们称为 横切关联( cross-cutting concerns)。 React.createClass 可以通过继承来实现组件间公用相同方法。

一个通用的案例是一个组件需要定期更新自己的状态,只要使用setInterval()就可以实现。但是当您不再需要它来节省内存时,取消定时器是很重要的。React提供了生命周期方法来通知创建和销毁事件。下面的代码创建了一个肩带的混合器,混合器的作用是当组件被销毁之前,可以清除已有的定时器:

// 定义一个混合器
var SetIntervalMixin = {
  //组件将要被渲染时调用
  componentWillMount: function() {
    this.intervals = [];
  },
  // 设置定时器方法
  setInterval: function() {
    this.intervals.push(setInterval.apply(null, arguments));
  },

  //组件将要被卸载时调用
  componentWillUnmount: function() {
    this.intervals.forEach(clearInterval);
  }
};

var TickTock = React.createClass({
  mixins: [SetIntervalMixin], // 设定混合器
  getInitialState: function() {
    return {seconds: 0};
  },
  componentDidMount: function() {
    this.setInterval(this.tick, 1000); // 调用混合器中的setInterval 方法
  },
  tick: function() {
    this.setState({seconds: this.state.seconds + 1});
  },
  render: function() {
    return (
      <p>
        React has been running for {this.state.seconds} seconds.
      </p>
    );
  }
});

ReactDOM.render(
  <TickTock />,
  document.getElementById('example')
);

如果组件使用了多个混合器并且很多混合器定义了相同的生命周期方法,比如同时定义了componentWillUnmount方法当组件卸载时注销某些资源。所有混合器的生命周期方法都会被调用,React会按照混合器设定的顺序来执行。

不使用JSX

对于React来说JSX并不是必须要使用的表达式。当在环境中不想在家额外的编译工具时尤其适用。

每一个JSX的元素都仅仅是React.createElement(component, props, ...children)的语法糖,所以任何使用JSX表达式实现的内容都可以直接用JavaScript来实现。

例如下面使用JSX编码的例子:

class Hello extends React.Component {
  render() {
    return <div>Hello {this.props.toWhat}</div>;
  }
}

ReactDOM.render(
  <Hello toWhat="World" />,
  document.getElementById('root')
);

如果我们不想使用JSX,可以将其修改为:

class Hello extends React.Component {
  render() {
    return React.createElement('div', null, `Hello ${this.props.toWhat}`);
  }
}

ReactDOM.render(
  React.createElement(Hello, {toWhat: 'World'}, null),
  document.getElementById('root')
);

如果你对JSX如何转换成JavaScript有很强的兴趣,可以打开这个在线编译器试试:the online Babel compiler

组件被编译成一段字符串、由 React.Component创建的子类或者一个普通无状态的组件。

如果对编码时每次都要键入长长React.createElement感到痛苦,一个常见的模式是分配一个别名:

const e = React.createElement;

ReactDOM.render(
  e('div', null, 'Hello World'),
  document.getElementById('root')
);
相关文章
|
24天前
|
存储 前端开发
在React框架中,如何使用对象来管理组件的状态
在React中,组件状态通过`state`对象管理,利用`setState`方法更新状态。状态变化触发组件重新渲染,实现UI动态更新。对象结构清晰,便于复杂状态管理。
|
3月前
ES6中map对象的使用,确实比Object好使哈
ES6中Map对象的使用优势,包括任意类型作为键、直接获取大小、增删查改操作等。Map的键可以是函数、对象、NaN等,支持forEach循环和for...of循环。
35 1
ES6中map对象的使用,确实比Object好使哈
|
2月前
|
Python
通过 type 和 object 之间的关联,进一步分析类型对象
通过 type 和 object 之间的关联,进一步分析类型对象
64 3
|
2月前
|
JavaScript 前端开发 大数据
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
35 0
|
3月前
|
JSON 前端开发 中间件
React读取properties配置文件转化为json对象并使用在url地址中
本文介绍了如何在React项目中读取properties配置文件,将其内容转化为JSON对象,并在请求URL地址时使用这些配置。文章详细说明了异步读取文件、处理字符串转换为JSON对象的过程,并提供了一个封装函数,用于在发起请求前动态生成配置化的URL地址。
97 1
|
4月前
|
数据安全/隐私保护
作用域通信对象:session用户在登录时通过`void setAttribute(String name,Object value)`方法设置用户名和密码。点击登录按钮后,跳转到另外一个页面显示用户
该博客文章通过示例演示了如何使用session对象的`setAttribute`和`getAttribute`方法在不同页面间传递和显示用户的用户名和密码信息,并说明了如何设置会话的有效期。
作用域通信对象:session用户在登录时通过`void setAttribute(String name,Object value)`方法设置用户名和密码。点击登录按钮后,跳转到另外一个页面显示用户
|
4月前
|
SQL 存储 数据库
|
4月前
【Azure Developer】使用PowerShell Where-Object方法过滤多维ArrayList时候,遇见的诡异问题 -- 当查找结果只有一个对象时,返回结果修改了对象结构,把多维变为一维
【Azure Developer】使用PowerShell Where-Object方法过滤多维ArrayList时候,遇见的诡异问题 -- 当查找结果只有一个对象时,返回结果修改了对象结构,把多维变为一维
网易:所有的对象最终都会继承自 Object.prototype ? ——原型链(二)详细讲解!
网易:所有的对象最终都会继承自 Object.prototype ? ——原型链(二)详细讲解!
|
4月前
|
JavaScript
网易:所有的对象最终都会继承自 Object.prototype ? ——原型链(一)详细讲解!
网易:所有的对象最终都会继承自 Object.prototype ? ——原型链(一)详细讲解!