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

       最近在空闲之余学习了一下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的代码,很容易看懂的,如果对上面我的描述还有什么疑问的童鞋们,欢迎留言,我将会一一作答。


     


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值