(React启蒙)理解React组件

作者: 7091a52ac9e5 | 来源:发表于2016-09-16 16:29 被阅读1550次

    本文将首先讲述如何通过React nodes创建基础的React组件,然后进一步剖析React组件内部的点滴,包括该如何理解React组件,获取React组件实例的两种办法,React事件系统,对React生命周期函数的理解,获取React组件的子组件和子节点的方法,字符串ref和函数式ref,以及触发React组件重新渲染的四种方法。
    本文是React启蒙系列的第六章,依旧讲的是React的基础使用方法,但是如果你对上面提到的概念有不理解或不熟悉的地方,跳到对应地方观看阅读,你应该会能有所收获。

    理解React组件

    在具体说明如何创建React组件的语法之前,对什么是React组件,其存在的意思及其划分依据等做一个论述是很有必要的。

    我们设想现在有一个webApp,这个app可以用来实现很多功能,依据功能,我们可以把其划分为多个功能碎片。要实现这么一个功能碎片,可能需要更多更小的逻辑单元,甚至还可以继续分。而我们编程其实就是在有一个总体轮廓的前提下,通过解决一个个小小的问题来解决一个小问题,解决一个个小问题来实现软件的开发。React组件就是这样,你可以就把它当做一个个可组合的功能单元。

    以一个登陆框为例,登录框本身就是网站的一个组件,但是其内包含诸如文本输入框,登陆按钮等,当然如果你想要做的只是最基础的功能,输入框和按钮等可以只是一个个React 节点,但是如果你想为输入框加上输入检测,输入框可能就有必要写成一个单独的组件了,这样也有利于复用,之后需要做的可能只是简单的通过props传入不同的参数就可以实现不同的检测。假想我们现在的登录框组件,包含React <Button>元素形成登录按钮,也包含多个文本输入检测组件。那么父组件的作用一方面在于聚合小组件形成更复杂的功能单元,另一方面在于为子组件信息的沟通提供渠道(比如说在满足一定的输入条件后,登录按钮的状态从不可点击变为可点击)。

    创建React组件

    React组件通过调用React.createClass()方法创建,该方法需要传入一个对象形式的参数。在该对象中可以为所创建组件配置各种参数,其可用参数如下表:

    方法(配置参数)名称 描述
    render() 必填,通常为一个返回React nodes或者其它组件的函数
    getInitialState() 一个用于设置最初的state的函数,返回一个对象
    getDefaultProps() 一个用于设置默认props的函数,返回值为一个对象
    propTypes 一个用于验证特定props类型的对象
    mixins 组件间共享方法的途径
    statics 一个由多个静态方法组成的对象,静态方法中不能直接调用propsstate(可通过参数)
    displayName 是一个用于命名组件的字符串,用于展示调试信息,使用JSX时将自动设置??
    componentWillMount() 在组件首次渲染前触发,只会触发一次
    componentDidMount() 在组件首次渲染后触发,只会触发一次
    componentWillReceiveProps() 在组件将接受新props时触发
    shouldComponentUpdate() 组件再次渲染前触发,可用于判断是否需要再次渲染
    componentWillUpdate() 组件再次渲染前立即触发
    componentDidUpdate() 组件渲染后立即触发
    componentWillUnmount() 组件卸载前立即触发

    在上述所以方法中,最重要且必不可少的是render(),它的作用是返回React节点和组件,其它所有的方法是可选的。

    实际写一个例子总比空说要容易理解,以下是使用React的React.createClass()创建的Timer组件

    var Timer = React.createClass({ 
        getInitialState: function() { 
            return {
                secondsElapsed: Number(this.props.startTime) || 0
            };
        },
        tick: function() { //自定义方法
            this.setState({
                secondsElapsed: this.state.secondsElapsed + 1
            });
        },
        componentDidMount: function() {//生命周期函数
            this.interval = setInterval(this.tick, 1000);
        },
        componentWillUnmount: function() {//生命周期函数
            clearInterval(this.interval);
        },
        render: function() { //使用JSX返回节点
            return (
                <div>
                    Seconds Elapsed: {this.state.secondsElapsed}
                </div>
            );
        }
    });
    
    ReactDOM.render(< Timer startTime = "60" / >, app); //pass startTime prop, used for state
    

    点击JSFiddle查看效果

    现在如果对上述组件创建的代码有所疑惑也不要紧,本文接下来将一步步的介绍上述代码中设计都的各个概念,包括this,生命周期函数,React返回值的格式,如何在React中自定义函数,以及React组件中事件的定义等等。

    在此需要注意的是组件名是以大写开头的。

    当一个组件被创建(挂载)以后,我们就可以使用组件的API了,一个组件包含以下四个API
    ** this.setState(),**

    this.setState({mykey: 'my new value'});  
    this.setState(function(previousState, currentProps) 
            { return {myInteger: previousState.myInteger + 1};
             }); 
    

    作用:
    用以重新渲染组件或者子组件

    ** replaceState()**

     this.replceState({mykey: 'my new value'}); 
    

    作用:
    效果和setState()类似,不过并不会和老的状态合并,而是直接删除老的状态,应用新的状态。

    forceUpdate()

         this.forceUpdate(function(){//callback}); 
    

    作用:
    调用此方法将跳过组件的shouldComponentUpdate()事件,直接调用render()

    ** isMounted()**

    this.isMounted()
    

    作用
    判断组件是否被挂载在DOM中,组件被挂载返回true,否则返回false

    最常用的组件API是setState(),后文还会细讲。

    小结

    • componentWillUnmount,componentDidUpdate, componentWillUpdate, shouldComponentUpdate, componentWillReceiveProps, componentDidMount, componentWillMount等方法被称作React 组件的生命周期函数,它们会在组件生命过程的不同阶段被触发。
    • React.createClass()是一个方便的创建组件实例的方法;
    • render()方法应该保持纯洁;

    render()方法中不能更改组件状态

    React组件的返回值

    上文已经提到每个React组件必须有的方法就是render(),这个方法的返回值只能是一个react 节点或一个react组件,这个节点或组件中可以包含任意多的子节点或者子元素。在下面的例子中我们可以看到在<reactNode>中包含了多个子节点。

    var MyComponent = React.createClass({
      render: function() {
        return <reactNode> <span>test</span> <span>test</span> </reactNode>;
      }
    });
    
    ReactDOM.render(<MyComponent />, app);
    

    值得注意的地方在于,如果你想返回的react 节点超过一行,应该用括号把返回值包围起来,如下所示

    var MyComponent = React.createClass({
      render: function() {
        return (
            <reactNode> 
                <span>test</span>
                <span>test</span> 
            </reactNode>
        );
      }
    });
    
    ReactDOM.render(<MyComponent />, app);
    

    另一个值得注意的地方是返回值最外层不能出现多个节点(组件),否者会报错

    var MyComponent = React.createClass({
      render: function() {
        return (
                <span>test</span>
                <span>test</span> 
        );
      }
    });
    
    ReactDOM.render(<MyComponent />, app);
    

    上述代码就会报错,报错信息如下

    babel.js:62789 Uncaught SyntaxError: embedded: Adjacent JSX elements must be wrapped in an enclosing tag (10:3)
       8 |     return (
       9 |             <span>test</span>
    > 10 |             <span>test</span>
         |    ^
      11 |     );
      12 |   }
      13 | });
    

    一般来说开发者会在最外层加上一个<div>元素包裹其它节点以避免此类错误。

    同样,如果return()中的最外层出现了多个组件,也会出错。

    获取组件实例的两种方法

    当一个组件被render后,一个组件便通过传入的参数实例化了,我们有两种办法获取这个实例及其内部属性(this.propsthis.setState())。

    第一种方法就是使用this关键字,在组件内部的方法中使用this我们发现,这个this指向的就是该组件实例。

    var Foo = React.createClass({
        componentWillMount:function(){ console.log(this) },
        componentDidMount:function(){ console.log(this) },
        render: function() {
            return <div>{console.log(this)}</div>;
        }
    });
    
    ReactDOM.render(<Foo />, document.getElementById('app'));
    

    获取某组件实例的另外一种方法是调用ReactDOM.render()方法,这个方法的返回值是最外层的组件实例。
    看如下代码可以更好的理解这句话

    var Bar = React.createClass({
        render: function() {
            return <div></div>;
        }
    });
    
    var foo; //store a reference to the instance outside of function
    
    var Foo = React.createClass({
        render: function() {
            return <Bar>{foo = this}</Bar>;
        }
    });
    
    var FooInstance = ReactDOM.render(<Foo />, document.getElementById('app'));
    
    console.log(FooInstance === foo); //true,说明返回值和指向一致
    

    小结
    this的最常见用法就是在一个组件内调用该组件的各个属性和方法,如this.props.[NAME OF PROP]this.props.children,this.state,this.setState(),this.replaceState()等。

    在组件上定义事件

    第四章和第五章已经多次介绍过React的事件系统,事件可以被直接添加都React节点上,下面的代码示例中,我们添加了两个React事件(onClick&onMouseOver)到React<div>节点中

    var MyComponent = React.createClass({
        mouseOverHandler:function mouseOverHandler(e) {
                console.log('you moused over');
                console.log(e); //e is sysnthetic event instance
            },
        clickHandler:function clickhandler(e) {
                console.log('you clicked');
                console.log(e); //e is sysnthetic event instance
            },
        render:function(){
            return (
    <div onClick={this.clickHandler} onMouseOver={this.mouseOverHandler}>click or mouse over</div>
            )
        }
    });
    
    ReactDOM.render(<MyComponent />, document.getElementById('app'));
    

    点击JSFiddle查看效果

    事件可以被看做是特殊的props,只是React对这些特殊的props的处理方式和普通的props有所不同。
    这种不同表现在会自动为事件的回调函数绑定上下文,在下面的示例中,回调函数中的this指向了组件实例本身。

    var MyComponent = React.createClass({
        mouseOverHandler:function mouseOverHandler(e) {
                console.log(this); //this is component instance
                console.log(e); //e is sysnthetic event instance
            },
        render:function(){
            return (
                <div onMouseOver={this.mouseOverHandler}>mouse over me</div>
            )
        }
    });
    
    ReactDOM.render(<MyComponent />, document.getElementById('app'));
    

    React所支持的所以事件可见此表

    小结

    • React规范化了事件在不同浏览器中的表现,你可以放心的跨浏览器使用;

    • React事件默认在事件冒泡阶段(bubbling)触发,如果想在事件捕获阶段触发需要在事件名后加上Capture(如onClick变为onClickCapture);

    • 如果你想获知浏览器事件的详情,你可以通过在回调函数中查看SyntheticEvent对象中的nativeEvent值;

    • React实际上并未直接为React nodes添加事件,它使用的是event delegation事件委托机制

    • 想要阻止事件冒泡,需要手动调用e.stopPropagation()e.preventDefault(),不要直接使用returning false,

    • React其实并没有支持所有的JS事件,不过它还提供额外的生命周期函数以供使用React lifecycle methods.

    组件组合

    React组件的render()方法中可以包含对其它组件的引用,这使得组件之间可以嵌套,一般我们把被嵌套的组件称为嵌套组件的子组件。

    下例中组件BadgeList包含了BadgeBill和BadgeTom两个组件。

    var BadgeBill = React.createClass({
        render: function() {return <div>Bill</div>;}
    });
    
    var BadgeTom = React.createClass({
        render: function() {return <div>Tom</div>;}
    });
    
    var BadgeList = React.createClass({
        render: function() {
            return (<div>
                <BadgeBill/>
                <BadgeTom />
            </div>);
        }
    });
    
    ReactDOM.render(<BadgeList />, document.getElementById('app'));
    

    此处为展示嵌套关系,代码有所简化。

    小结

    • 编写可维护性UI的关键之一在于可组合组件,React组件天然适用这一原理;
    • render方法中,组件和HTML可以组合使用;

    React组件的生命周期函数

    每个组件都具有一系列的发生在其生命中不同阶段的事件,这些事件被称为生命周期函数。

    生命周期函数可以理解为React为组件的不同阶段提供了的钩子函数,用以更好的操作组件,下例是一个定时器组件,其在不同生命周期函数中执行了不同的事件

    var Timer = React.createClass({
        getInitialState: function() { 
            console.log('getInitialState lifecycle method ran!');
            return {secondsElapsed: Number(this.props.startTime) || 0};
        },
        tick: function() {
            console.log(ReactDOM.findDOMNode(this));
            if(this.state.secondsElapsed === 65){
                ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).parentNode);
                return;
            }
            this.setState({secondsElapsed: this.state.secondsElapsed + 1});
        },
        componentDidMount: function() {
            console.log('componentDidMount lifecycle method ran!');
            this.interval = setInterval(this.tick, 1000);
        },
        componentWillUnmount: function() {
            console.log('componentWillUnmount lifecycle method ran!');
            clearInterval(this.interval);
        },
        render: function() {
            return (<div>Seconds Elapsed: {this.state.secondsElapsed}</div>);
        }
    });
    
    ReactDOM.render(< Timer startTime = "60" / >, app);
    
    

    组件的生命周期可被分为挂载(Mounting),更新(Updating)和卸载(UnMounting)三个阶段。

    下面将对不同阶段各函数的功能及用途进行描述,弄清这一点很重要
    挂载阶段

    这是React组件生命周期的第一个阶段,也可以称为组件出生阶段,这个阶段组件被初始化,获得初始的props并定义将会用到的state,此阶段结束时,组件及其子元素都会在UI中被渲染(DOM,UIview等),我们还可以对渲染后的组件进行进一步的加工。这个阶段的所有方法在组件生命中只会被触发一次。React-in-depth

    对挂载阶段的生命周期函数的描述

    方法 描述
    getInitialState() 在组件挂载前被触发,富状态组件应该调用此方法以获得初始的状态值
    componentWiillMount() 在组件挂载前被触发,富状态组件应该调用此方法以获得初始的状态值
    componentWillMount() 组件被挂载后立即触发,在此可以对DOM进行操作了

    更新阶段

    这个阶段的函数会在组件的整个生命周期中不断被触发,这是组件一生中最长的时期。这个阶段的函数可以获得新的props,可以更改state,可以对用户的交互进行反应。React-in-depth

    对更新阶段的生命周期函数的描述

    方法 描述
    componentWillReceiveProps(object nextProps) 在组件接受新的props时被触发,可以用来比较新老props,并使用this.setState()来改变组件状态
    shouldComponentUpdate(object nextProps, object nextState) 此组件可以对比新老propsstate,用以确认该组件是否需要重新渲染,如果返回值为false,将跳过此次渲染,此方法常用于优化React性能
    componentWillUpdate(object nextProps, object nextState) 在组件重新渲染前被触发,此时不能再调用this.setState()state进行更改
    componentDidUpdate(object prevProps, object prevState) 在重新渲染后立即被触发,此时可调用新的DOM了

    卸载阶段

    这是组件生命的最后一个阶段,也可以被称为是组件的死亡阶段,此阶段对应组件从Native UI中卸载之时,具体说来可能是用户切换了页面,或者页面改变去除了某个组件,卸载阶段的函数只会被触发一次,然后该组件就会被加入浏览器的垃圾回收机制。React-in-depth

    方法 描述
    componentWillUnmount() 组件卸载前立即被触发,此阶段常用来执行一些清理工作(比如说清除setInterval

    对此阶段的生命周期函数的描述

    方法 描述
    componentWillUnmount() 组件卸载前立即被触发,此阶段常用来执行一些清理工作(比如说清除setInterval

    小结

    • componentDidMountcomponentDidUpdate 常用来加载第三方的库(此时真实DOM存在,可加载各种图表库)。
    • 组件挂载阶段的各事件执行顺序如下
      1. Initialize / Construction
      2. 获取初始的props,ES5中使用 getDefaultProps() (React.createClass),ES6中使用 MyComponent.defaultProps (ES6 class)
      3. 初始组件的state值,ES5中使用getInitialState() (React.createClass) ,ES6中使用 this.state = ...(ES6 constructor)
      4. componentWillMount()
      5. render()第一次渲染
      6. Children initialization & life cycle kickoff,子组件重复上述(1~5步)过程;
      7. componentDidMount()

    通过上面的过程分析,我们可以知道,在父元素执行componentDidMount()时,子元素和子组件都已经存在于真实DOM中了,因此在此可以放心调用。

    • 组件更新阶段各函数执行顺序如下

      1. componentWillReceiveProps():比较新老props,对state进行改变;
      2. shouldComponentUpdate():判断组件是否需要重新渲染
      3. render():重新渲染
      4. Children Life cycle methods:子元素重复上述过程
      5. componentWillUpdate():此阶段可以调用新的DOM了
    • 组件卸载阶段各函数执行顺序如下

      1. componentWillUnmount()
      2. Children Life cycle methods:触发子元素的生命周期函数,也将被卸载
      3. 被浏览器从内存中清除;

    获取子组件和子节点的方法

    如果一个组件包含子组件或React节点(如<Parent><Child /></Parent><Parent><span>test<span></Parent>),这些子节点和子组件可以通过React的this.props.children的方法来获取。

    下面的例子展示了如何使用this.props.children

    var Parent2 = React.createClass({
      componentDidMount: function() {
        //将会获得<span>child2text</span>,
        console.log(this.props.children);
        //将会获得 child2text, 或得了子元素<span>的子元素
        console.log(this.props.children.props.children);
      },
    
      render: function() {return <div />;}
    });
    
    var Parent = React.createClass({
      componentDidMount: function() {
        //获得了一个数组 <div>test</div> <div>test</div>
        console.log(this.props.children);
        //获得了这个数组中的对应子元素中的子元素 childtext,
        console.log(this.props.children[1].props.children);
      },
    
      render: function() {return <Parent2><span>child2text</span></Parent2>;}
    });
    
    ReactDOM.render(
      <Parent><div>child</div><div>childtext</div></Parent>,
      document.getElementById('app')
    );
    

    观察上述的代码可以看出以下几点

    • Parent组件实例的this.props.children获取到由直系子元素组成的数组,可以对子元素套用此方法获得子元素(组件)的子元素(组件)(this.props.children[1].props.children);
    • 子元素指的是由该实例围起来的元素,而非该实例内部元素;
    方法 描述
    React.Children.map(this.props.children, function(){}) 在每一个直接子级(包含在 children 参数中的)上调用 fn 函数,此函数中的 this 指向 上下文。如果 children 是一个内嵌的对象或者数组,它将被遍历,每个键值对都会添加到新的 Map。如果 children 参数是 null 或者 undefined,那么返回 null 或者 undefined 而不是一个空对象。
    React.Children.forEach(this.props.children, function(){}) 类似于Children.map()但是不会反回数组
    React.Children.count(this.props.children) 返回组件子元素的总数量,其数目等于Children.map()Children.forEach()的执行次数。
    React.Children.only(this.props.children) 返回唯一的子元素否则报错
    React.Children.toArray(this.props.children) 返回一个由各子元素组成的数组,如果你想在render事件中操作子元素的集合时,这个方法特别有用,尤其是在重新排序或分割子元素时

    为了更好的操作this.props.children包含的是一组元素,React还提供了以下方法

    方法 描述
    React.Children.map(this.props.children, function(){}) 在每一个直接子级(包含在 children 参数中的)上调用 fn 函数,此函数中的 this 指向 上下文。如果 children 是一个内嵌的对象或者数组,它将被遍历,每个键值对都会添加到新的 Map。如果 children 参数是 null 或者 undefined,那么返回 null 或者 undefined 而不是一个空对象。
    React.Children.forEach(this.props.children, function(){}) 类似于Children.map()但是不会反回数组
    React.Children.count(this.props.children) 返回组件子元素的总数量,其数目等于Children.map()Children.forEach()的执行次数。
    React.Children.only(this.props.children) 返回唯一的子元素否则报错
    React.Children.toArray(this.props.children) 返回一个由各子元素组成的数组,如果你想在render事件中操作子元素的集合时,这个方法特别有用,尤其是在重新排序或分割子元素时

    小结

    • 当只有一个子元素时,this.props.children之间返回该子元素,不会用一个数组包裹着该子元素;
    • 需要注意的是children并非某组件内部的节点,而是由该组件包裹的组件或节点‘

    两种ref

    ref属性使得我们获取了对某一个React节点或某一个子组件的引用,这个在你需要直接操作DOM时非常有用。

    字符串ref的使用很简单,可分为两步:

    • 一是给你想引用的的子元素或组件添加ref属性,
    • 然后在本组件中通过this.refs.value(你所设置的属性名)即可引用;

    不过还存在一种函数式的ref,看下面的例子

    var C2 = React.createClass({
      render: function() {return <span ref={function(span) {console.log(span)}} />}
    });
    
    var C1 = React.createClass({
      render: function() {return(
            <div>
                <C2 ref={function(c2) {console.log(c2)}}></C2>
                <div ref={function(div) {console.log(div)}}></div>
            </div>)}
    });
    
    ReactDOM.render(<C1 ref={function(ci) {console.log(ci)}} />,document.getElementById('app'));
    

    上述例子的console结果都是指向ref所在的组件或元素,通过console的结果我们也可以发现,打印结果说明其指向的是真实的HTML DOM而非Virtual DOM。

    如果不想用字符串ref,通过下面的方法也可以引用到你想引用的节点

    var MyComponent = React.createClass({
      handleClick: function() {
        // focus()对真实DOM元素有效
          this.textInput.focus();
      },
      render: function() {
        // ref中传入了一个回调函数,把该节点本身赋值给this.input
        return (
          <div>
            <input type="text" ref={(thisInput) => {this.textInput = thisInput}} />
            <input
              type="button"
              value="Focus the text input"
              onClick={this.handleClick}
            />
          </div>
        );
      }
    });
    
    ReactDOM.render(
      <MyComponent />,
      document.getElementById('app')
    );
    

    小结

    • 对无状态函数式组件不能使用ref,因为这种组件并不会返回一个实例;
    • ref有两种,字符串ref和函数式ref,不过字符串ref(通过refs调用这种)在未来可能被放弃,函数式ref是趋势;
    • 组件有ref,可以通过ref调用该组件内部的方法;
    • 使用行内函数表达式使用ref意味着每次更新React都会将其视为一个不同的函数对象,ref中的函数会以null为参数被立即执行(和在实例中调用不冲突)。比如说,当ref所指向的对象被卸载时,或者ref改变时,老的的ref函数都会以null为参数被调用。
    • 对应ref的使用,React官方有两点建议:
      1. ref允许你直接操作节点,这一点有些情况下是非常方便的,不过需要注意的是,如果可以通过更改state来达到你想要的效果,那就不要随便使用ref啦;
      2. 如果你刚刚接触React,在你想用ref的时候,还是尽量多思考一下看能不能用state来解决,仔细思考你会发现,state可以解决大部分操作问题的,比较直接操作DOM并未React的初衷。

    重新渲染一个组件

    我们已经接触了ReactDOM.render()方法,这个方法使得组件及其子组件被初始化渲染。在这次渲染之后,React为我们提供了两种方法来重新渲染某个组件

    1. 在组件内调用setState()方法;
    2. 在组件中调用fouceUpdate()方法;

    每当一个组件被重新渲染时,其子组件也会被重新渲染(在Virtual DOM中发生,在真实DOM中表现出来)。不过需要注意的是Virtual DOM的改变并不是一定在真实DOM中就会有所表现。

    在下面的例子中,ReactDOM.render(< App / >, app)初始化渲染了<App/>及其子组件<Timer/>,接下来的<App/>中的setInterval()事件调用this.setState()致使两个组件被重新渲染。在5秒后,setInterval()被清除,而在十秒后this.forceUpdate()被触发又使得页面被重新渲染。

    var Timer = React.createClass({
        render: function() {
          return (
            <div>{this.props.now}</div>
            )
        }
    });
    
    var App = React.createClass({
      getInitialState: function() {
        return {now: Date.now()};
      },
    
      componentDidMount: function() {
        var foo = setInterval(function() {
            this.setState({now: Date.now()});
        }.bind(this), 1000);
    
        setTimeout(function(){ clearInterval(foo); }, 5000);
        //DON'T DO THIS, JUST DEMONSTRATING .forceUpdate() 
        setTimeout(function(){ this.state.now = 'foo'; this.forceUpdate() }.bind(this), 10000);
      },
      
      render: function() {
          return (
            <Timer now={this.state.now}></Timer>
            )
        }
    });
    
    ReactDOM.render(< App / >, app);
    

    点击JSFiddle查看效果

    后文

    从开始翻译本书到现在已有一个多月,基础的翻译工作终于算是告一段落。
    《React Enlightenment》的第七章和第八章讲述的是React的propsstate已由@linda102翻译完成。

    在大概一个多月前看到本书原文时,我已经用了快五个月React,但是看完本书还是挺有收获。

    翻译本书的初衷有两点,一是加强自己对React基础的理解,二是回想起,我在初学React时曾购买过国内的一本关于React的基础书籍,价格是四十多,但是其实看完并未有太多收获,该书大多就是翻译的官方文档,而且翻译的也不全面,并不那么容易理解,所以希望这篇译文对初学者友好,让初学者少走弯路。

    由于翻译时间和水平都有限,译文内部不可避免存在一些不恰当的地方,如果您在阅读的过程中有好的建议,请直接提出,我会尽快修改。谢谢

    一些有用的链接

    本书全文在Gitbook中观看

    本文英文原文

    相关文章

      网友评论

      本文标题:(React启蒙)理解React组件

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