React实践系列笔记-Components

Components

React提供了和以往不一样的方式来看待视图,它以组件开发为基础。组件是React的核心概念,React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。对React应用而言,你需要分割你的页面,使其成为一个个的组件。也就是说,你的应用是由这些组件组合而成的。你可以通过分割组件的方式去开发复杂的页面或某个功能区块,并且组件是可以被复用的。这个过程大概类似于用乐高积木去瓶装不同的物体。我们称这种编程方式称为**组件驱动开发**。

Declaration:组件声明

React是可以同时渲染HTML标签与组件的,但是要注意的是,一般Tags元素都是小写开头,而Component都是以大写字母开头,以下面为例:
var myDivElement = <div className="foo" />;
React.render(myDivElement,document.getElementById('example'));
而如果需要渲染一个Component:
var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
React.render(myElement,document.getElementById('example'));

LifeCycle

组件的生命周期分成三个状态:

  • Mounting:已插入真实 DOM,即Initial Render

  • Updating:正在被重新渲染,即Props与State改变

  • Unmounting:已移出真实 DOM,即Component Unmount

    React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。

  • componentWillMount()

  • componentDidMount()

  • componentWillUpdate(object nextProps,object nextState)

  • componentDidUpdate(object prevProps,object prevState)

  • componentWillUnmount()

此外,React 还提供两种特殊状态的处理函数。

  • componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
  • shouldComponentUpdate(object nextProps,object nextState):组件判断是否重新渲染时调用

Ini­tial Render

Props Change

State Change

这里可以看出,Props比State的改变会有多出一个shouldComponentUpdate的回调方法。

Com­po­nent Unmount

总结而言,一个完整的React Component的写法应该如下:
/** * @jsx React.DOM */

var React = require('react'),MyReactComponent = React.createClass({

    // The object returned by this method sets the initial value of this.state
    getInitialState: function(){
        return {};
    },// The object returned by this method sets the initial value of this.props
    // If a complex object is returned,it is shared among all component instances 
    getDefaultProps: function(){
        return {};
    },// Returns the jsx markup for a component
    // Inspects this.state and this.props create the markup
    // Should never update this.state or this.props
    render: function(){
        return (<div></div>); },// An array of objects each of which can augment the lifecycle methods mixins: [],// Functions that can be invoked on the component without creating instances statics: { aStaticFunction: function(){} },// -- Lifecycle Methods -- // Invoked once before first render componentWillMount: function(){ // Calling setState here does not cause a re-render },// Invoked once after the first render componentDidMount: function(){ // You now have access to this.getDOMNode() },// Invoked whenever there is a prop change // Called BEFORE render componentWillReceiveProps: function(nextProps){ // Not called for the initial render // Previous props can be accessed by this.props // Calling setState here does not trigger an an additional re-render },// Determines if the render method should run in the subsequent step // Called BEFORE a render // Not called for the initial render shouldComponentUpdate: function(nextProps,nextState){ // If you want the render method to execute in the next step // return true,else return false return true; },// Called IMMEDIATELY BEFORE a render componentWillUpdate: function(nextProps,nextState){ // You cannot use this.setState() in this method },// Called IMMEDIATELY AFTER a render componentDidUpdate: function(prevProps,prevState){ },// Called IMMEDIATELY before a component is unmounted componentWillUnmount: function(){ } }); module.exports = MyReactComponent;

Props

getDefaultProps

设置默认的Props.

Attributes

children

this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点。

var NotesList = React.createClass({
      render: function() {
        return (
          <ol> { this.props.children.map(function (child) { return <li>{child}</li> }) } </ol> ); } }); React.render( <NotesList> <span>hello</span> <span>world</span> </NotesList>,document.body );

其效果图如下所示:

[enter description here][5]

Validation

React.createClass({
  propTypes: {
    // You can declare that a prop is a specific JS primitive. By default,these
    // are all optional.
    optionalArray: React.PropTypes.array,optionalBool: React.PropTypes.bool,optionalFunc: React.PropTypes.func,optionalNumber: React.PropTypes.number,optionalObject: React.PropTypes.object,optionalString: React.PropTypes.string,// Anything that can be rendered: numbers,strings,elements or an array
    // containing these types.
    optionalNode: React.PropTypes.node,// A React element.
    optionalElement: React.PropTypes.element,// You can also declare that a prop is an instance of a class. This uses
    // JS's instanceof operator.
    optionalMessage: React.PropTypes.instanceOf(Message),// You can ensure that your prop is limited to specific values by treating
    // it as an enum.
    optionalEnum: React.PropTypes.oneOf(['News','Photos']),// An object that could be one of many types
    optionalUnion: React.PropTypes.oneOfType([
      React.PropTypes.string,React.PropTypes.number,React.PropTypes.instanceOf(Message)
    ]),// An array of a certain type
    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),// An object with property values of a certain type
    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),// An object taking on a particular shape
    optionalObjectWithShape: React.PropTypes.shape({
      color: React.PropTypes.string,fontSize: React.PropTypes.number
    }),// You can chain any of the above with `isRequired` to make sure a warning
    // is shown if the prop isn't provided.
    requiredFunc: React.PropTypes.func.isRequired,// A value of any data type
    requiredAny: React.PropTypes.any.isRequired,// You can also specify a custom validator. It should return an Error
    // object if the validation fails. Don't `console.warn` or throw,as this
    // won't work inside `oneOfType`.
    customProp: function(props,propName,componentName) {
      if (!/matchme/.test(props[propName])) {
        return new Error('Validation failed!');
      }
    }
  },/* ... */
});

State

React不提倡数据的双向绑定,而在用户行为下面产生的数据更新,React建议还是通过事件机制来处理。譬如下述例子中,输入框文本内容的改变,还是通过onChange事件,然后出发状态机的变化。

var LikeButton = React.createClass({
      getInitialState: function() {
        return {liked: false};
      },handleClick: function(event) {
        this.setState({liked: !this.state.liked});
      },render: function() {
        var text = this.state.liked ? 'like' : 'haven\'t liked';
        return (
          <p onClick={this.handleClick}> You {text} this. Click to toggle. </p> ); } }); React.render( <LikeButton />,document.getElementById('example') );

Props与State对比

参考资料

[Props VS State][6]

组件的主要职责是将原始数据转化为HTML中的富文本格式,而Props与State协作完成这件事,换言之,Props与State的并集即是全部的原始数据。Props与State之间也是有很多交集的,譬如:

  • Props与State都是JS对象。
  • Props与State的值的改变都会触发界面的重新渲染。
  • Props与State都是确定性的,即在确定的Props或者State的值的情况下都会得出相同的界面。

不过Props顾名思义,更多的是作为Component的配置项存在。Props往往是由父元素指定并且传递给自己的子元素,不过自身往往不会去改变Props的值。另一方面,State在组件被挂载时才会被赋予一个默认值,而常常在与用户的交互中发生更改。往往一个组件独立地维护它的整个状态机,可以认为State是一个私有属性。他们的对比如下:

描述 Props State
是否可以从父元素获取初始值 Yes Yes
是否可以被父元素改变 Yes No
是否可以设置默认值 Yes Yes
是否可以在组件内改变 No Yes
是否可以设置为子元素的初始值 Yes Yes
是否可以在子元素中改变 Yes No

Multiple Components

Children:组件Tag内包裹

上文中提及过,一种利用组件内包裹的方式动态定义组件的方式,可以利用Props的children属性来获取所有包裹住的Dom对象。

Nested Components

React主打的是组件驱动型编程,往往可以将一个大的组件拆分为几个小的组件,这里以头像控件为例:
var Avatar = React.createClass({
  render: function() {
    return (
      <div> <ProfilePic username={this.props.username} /> <ProfileLink username={this.props.username} /> </div> ); } }); var ProfilePic = React.createClass({ render: function() { return ( <img src={'https://graph.facebook.com/' + this.props.username + '/picture'} /> ); } }); var ProfileLink = React.createClass({ render: function() { return ( <a href={'https://www.facebook.com/' + this.props.username}> {this.props.username} </a> ); } }); React.render( <Avatar username="pwh" />,document.getElementById('example') );
有时候在某个组件内调用另一个组件,并不会进行渲染,譬如:
class Home extends React.Component {
  render() {
    return (
      <div> <map/> </div> ); } } var map = React.createClass({ render: function() { return ( <div id="map-canvas"> <span>hello</span> </div> ); } }); 
这里的map并不会被识别,应该把map变为Map,可以参考[这里](https://facebook.github.io/react/docs/jsx-in-depth.html#html-tags-vs.-react-components)。

Mixins:组件的继承

虽然组件的原则就是模块化,彼此之间相互独立,但是有时候不同的组件之间可能会共用一些功能,共享一部分代码。所以 React 提供了`mixins`这种方式来处理这种问题。Mixin 就是用来定义一些方法,使用这个 mixin 的组件能够自由的使用这些方法(就像在组件中定义的一样),所以 mixin 相当于组件的一个扩展,在 mixin 中也能定义“生命周期”方法。

比如一个定时器的 mixin:

var SetIntervalMixin = {
    componentWillMount: function() {
        this.intervals = [];
    },setInterval: function() {
        this.intervals.push(setInterval.apply(null,arguments));
    },componentWillUnmount: function() {
        this.intervals.map(clearInterval);
    }
};

var TickTock = React.createClass({
    mixins: [SetIntervalMixin],// Use the mixin
    getInitialState: function() {
        return {seconds: 0};
    },componentDidMount: function() {
        this.setInterval(this.tick,1000); // Call a method on the mixin
    },tick: function() {
        this.setState({seconds: this.state.seconds + 1});
    },render: function() {
        return (
            <p> React has been running for {this.state.seconds} seconds. </p> ); } }); React.render( <TickTock />,document.getElementById('example') );
React 的`mixins`的强大之处在于,如果一个组件使用了多个 mixins,其中几个`mixins`定义了相同的“生命周期方法”,这些方法会在组件相应的方法执行完之后按 mixins 指定的数组顺序执行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom