React学习笔记——如何创建React组件

来源:互联网 发布:摄像头软件 编辑:程序博客网 时间:2024/06/05 15:47

       最近在空闲之余学习了一下React,发现React入门比angular2较为容易很多(个人观点,不喜勿喷),代码逻辑非常简单,只要是有JavaScript基础的童鞋,都能看明白,想要入门的童鞋们,如果英文阅读能力还不错的,或者想要提高自己英文阅读水平的,可以看下React官网的的Tutorial,不喜欢英文教程的童鞋推荐去看一下阮一峰前辈的React入门实例教程 。

          React的核心是组件,其设计目的是提高代码复用率降低测试难度和代码复杂度

      React主要的语法是JSX语法,JSX 是JavaScript Xml的缩写,但其本质上不是XML,它是基于ECMASAcript标准的一种新特性,JSX可以理解为能直接写HTML的JS,和一般的HTML嵌套又有一定的区别,主要区别在于JSX能够使用求值表达式作为被嵌套的子节点,而一般的HTML嵌套只能使用语句作为嵌套的子节点,区别求值表达式和语句,主要看是否能够能否参与运算。

      JSX中的css样式是通过对象的形式传给style

<div style={key:value}></div>

      调用方法的方式也是如此

<div onClick={this.clickFn}></div>
      说这些也没啥用,我们先来看下如何创建一个组件,我这里写了一个轮播图的组件,用这个组件来说明一下:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Document</title>    <style type="text/css">        *{margin: 0;padding: 0; list-style: none;}        .wrap{height: 340px;width: 790px;margin: 100px auto; position: relative;overflow: hidden;}        .wrap ul{position: absolute;width: 3950px;}        .wrap ul li{height: 340px;float:left;}        .wrap ol{position: absolute;bottom: 10px; margin-left: 35%;}        .wrap ol li{            float:left;            height: 8px;            width: 10px;            margin-left: 30px;            line-height: 20px;            text-align: center;            border-radius: 50%;            cursor: pointer;            background-color:rgba(255,255,255,.5);            transition: all .25s;        }        .wrap ol li.active{            border-radius: 50%;            color: #fff;            background-color:rgba(0,0,0,.2);        }        .wrap ol li:hover{            border-radius: 50%;            color: #fff;            background-color:rgba(0,0,0,.2);            transform: scale(1.3);        }    </style>    <script src="../build/react.js"></script>    <script src="../build/react-dom.js"></script>    <script src="../build/browser.min.js"></script>    <script src="../build/jquery.min.js"></script></head><body><div class="wrap" id="wrap"></div><script type="text/babel">    var imgs = ['img/1.jpg','img/2.jpg','img/3.jpg','img/4.jpg','img/5.jpg']    var Carusel = React.createClass({        getInitialState:function () {            return {                index : 0,                timer : null,                wrap  : {},                pic   : {},                list  : [],            }        },        autoPlay:function() {            this.state.index++;            if (this.state.index >= this.state.list.length) {                this.state.index = 0;            }            this.handle(this.state.index);        },        change:function (index) {            this.state.index = index            clearInterval(this.timer);            this.handle(index)        },        handle:function (index) {            for(var j=0;j<this.state.list.length;j++){                if(j != index){                    this.state.list[j].className='';                }else{                    this.state.list[j].className='active';                }            }            $("#pic").stop(true, false).animate({left: -index * 790 + 'px'}, 500, function () {            })        },        componentDidMount:function () {            this.state.wrap = document.getElementById('wrap');            this.state.pic = document.getElementById('pic');            this.state.list = document.getElementById('list').getElementsByTagName('li');            this.state.list[0].className='active';            this.timer = setInterval(this.autoPlay, 3000);            var obj = this;            for(var i=0;i<this.state.list.length;i++){                this.state.list[i].id=i;                this.state.list[i].onmouseover=function(){                    clearInterval(this.timer);                    obj.change(this.id);                }            }        },        render:function () {            return (                    <div>                        <ul id="pic" onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>                            {                                imgs.map(function (img,index) {                                    return <li key={index}><img src={img}></img></li>                                })                            }                        </ul>                        <ol id="list">                            {                                imgs.map(function (img,index) {                                    return <li key={index}></li>                                })                            }                        </ol>                    </div>            )        },        onMouseEnter:function () {            clearInterval(this.timer);        },        onMouseLeave:function () {            this.timer=setInterval(this.autoPlay,3000);        }    });    ReactDOM.render(            <Carusel/>,            document.getElementById('wrap')    )</script></body></html>

          首先我们需要引入三个类库:(PS:这三个库必须首先加载)

              react.min.js - React 的核心库
              react-dom.min.js - 提供与 DOM 相关的功能
              Browser.js 的作用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。

      在不支持ES6的浏览器我们还需要再引入一个类库:
              babel.min.js - Babel 可以将 ES6 代码转为 ES5 代码,这样我们就能在目前不支持 ES6 浏览器上执行 React 代码。Babel 内嵌了对 JSX 的支持。通过将 Babel 和 babel-sublime 包(package)一同使用可以让源码的语法渲染上升到一个全新的水平。

      在使用JSX的地方需要注意,type都必须为 type="text/babel",这是React独有的写法,跟JavaScript不兼容,所以只要用到JSX的地方,都必须是用type="text/babel"进行声明,

      现在我们开始创建一个组件,创建组件的写法 为var Carusel = React.creatClass({}), 名字首字母必须大写,其中最主要的两个属性是render和componentDidMoun属性,render属性是必须的,这是用于输出组件,componentDidMoun是在组件输出完成后要执行的方法,说到这里。不得不提一下React组件的生命周期,React的生命周期中提供了10个不同的API,一一说解释之后应该就能明白生命周期了

     React 生命周期Api:

         1:getInitialState :作用于组件的实例,在实例创建时调用一次,用于初始化每个实例的state,此时可以访问this.props,但是两者有不同的地方,this.state访问的属性值时可以更改的,this.props访问的属性值是不可更改的。
         2:getDefaultProps:用于设置实例的默认值,作用于组件类,只调用一次,返回对象用于设置默认的props,对于引用值,会在实例中共享。

         3:componentWillMount:在Dom完成首次渲染之前调用,此时仍可以修改组件的state。

         4:render:在上面我们也说到了这个是必须要有的属性方法,它的作用就是创建虚拟的Dom,在这个方法的内部只能通过this.stated或者this.props的方式访问数据,它可以返回null ,false,或者任何React的组件,但是只能返回一个顶级组件,这里需要注意,而且还不能改变组件的状态,不能修改Dom的输出。

         5:componentDidMount:在上面也说了真实的Dom被渲染出来后调用,在该方法中可通过this.getDOMNode()访问到真实的DOM元素。此时已可以使用其他类库来操作这个DOM。不过得注意一点,该属性在服务端中,该方法不会被调用。

         6:componentWillReceiveProps:组件接收到新的props时调用,并将其作为参数nextProps使用,此时可以更改组件props及state。

componentWillReceiveProps: function(nextProps) {    if (nextProps.bool) {        this.setState({            bool: true        });    }}
        7:shouldComponentUpdate:组件是否应当渲染新的props或state,返回false表示跳过后续的生命周期方法,通常不需要使用以避免出现bug。在出现应用的瓶颈时,可通过该方法进行适当的优化。需要注意的是,在首次渲染期间或者调用了forceUpdate方法后,该方法不会被调用。

       8:componentWillUpdate:接收到新的props或者state后,进行渲染之前调用,此时不允许更新props或state。

       9:componentDidUpdate:完成渲染新的props或者state后调用,此时可以访问到新的DOM元素。

     10:componentWillUnmount:组件被移除之前被调用,可以用于做一些清理工作,在componentDidMount方法中添加的所有任务都需要在该方法中撤销,比如创建的定时器或添加的事件监听器。

     看完API的描述后,上述的代码应该就能明白了。我还得说一点,就是render在返回组件的时候,只能是返回一个标签对,不能返回两个兄弟元素标签,

render:function () {//render 用于输出组件,这是必须的一个属性    return (            <div>                <ul id="pic" onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>                    {                        imgs.map(function (img,index) {                            return <li key={index}><img src={img}></img></li>                        })                    }                </ul>                <ol id="list">                    {                        imgs.map(function (img,index) {                            return <li key={index}></li>                        })                    }                </ol>            </div>    )}

比如这里,如果返回的这个dom,ul跟ol外层没有div包裹的话,程序执行后将会报错,必须使用一个div进行包裹,对于ReactDom.render方法也是同样。除此之外在练习的过程中就没遇到其它的什么问题了。至于轮播图代码是很简单的纯JavaScript的代码,很容易看懂的,如果对上面我的描述还有什么疑问的童鞋们,欢迎留言,我将会一一作答。


     


原创粉丝点击