React快速进阶

上一篇文章,React入门 大体了解了, 如何基本的使用组件和更新组件. 如今,咱们来点新的~css

属性验证

React针对于props 专门提供了两种属性验证, 来保证组件的可复用性~ propTypesdefaultProps. propTypes用来设置属性是否必须, 类型等. defaultProps就是用来设置属性的默认值.node

class Search extends Component {
    constructor(){
        super();
        this.number = 0;
    }
    render() {
        return(
            <div>
                <span>{this.props.children}</span>
            </div>
            )
    }
}
Search.propTypes = {
    children:PropTypes.string.isRequired
}
Search.defaultProps={
    children:"default value"
}

这里,设置this.children属性是必须的,而且若是你不写的话, 他就会使用默认值,default value来替代. online demo
ok, 咱们来看一下, React提供了哪几种PropType value.
from pro reactreact

proptypes

而且,在设置类型的同时,你还能够在后面再写上isRequired这样的内容.PropTypes.array.isRequired.css3

还有一些其余的内容, like:npm

proptype desc
oneOfType 能够用来设置多种类型.PropTypes.oneOfType([PropTypes.string,PropTypes.number])
node 必须是可以渲染的类型,好比:numbers, strings, elements, or an array.
oneOf 只能是其中的某一个PropTypes.oneOf(['News', 'Photos'])

怎么写组件?

怎么写组件这个问题, 翻译一下就是,怎么使用state和props属性. 由于组件的render和state以及props是息息相关的~
比较好的实践是,state归父UI管, props归子UI管. 这里, 咱们用一个简单的demo来阐述一下. 写一个搜索框~babel

基本样式为:app

search

这个demo其实就一个中心点,经过onChange事件来控制内容信息的展现. 信息的展现,就是经过触发this.setState 方法来完成.
我这里, 就不贴代码了,直接放在online demo里了.ide

组件的生命周期

所谓的生命周期,实际上就是一些列触发或者不触发渲染的方法~
而涉及到这些渲染触发操做的, 大概就有4个过程:性能

  • Mounting动画

  • Unmounting

  • Props Change

  • State Change

咱们来讲一下,每一个过程对应状态的触发顺序.

Mounting

该过程表示渲染组件的过程. 简而言之就是将咱们写的组件类(class), 经过render 方法渲染到页面上. 具体触发顺序是:

  • Class: 已经书写好的UI 类

  • componentWillMount: 该方法会在render方法以前被invoke. 方法内部会设置好组件的state

  • render: 正式的触发方法

  • componentDidMount: 将节点正式渲染到页面上, 在该方法后面, 就能够实际操做DOM.

Unmounting

卸载组件的过程. 即:

<div>
    <single></single>
</div>

渲染为:

<div>
    {/* single component has been removed*/}
</div>

该过程实际上只会触发一个方法:

  • componentWillUnmount: 在DOM即将删除以前触发该方法, 因此你能够在该方法内部作一些事件的解绑

Props Change

看名字你们差很少已经猜出来了. 该过程就是主要处理props 内容的改变. 基本的过程为:

  • ComponentWillReciveProps: 当组件接收到新的props便会触发该方法. 若是你在该方法内调用this.setState其实是没有效果的.(Ps: 该方法其实并无什么x用)

  • shouldComponentUpdate: 检测是否组件须要从新渲染. 实际上就是经过该方法决定, render 方法是否能够直接跳过

  • componentWillUpdate: 新的props和state会被接收. 而且在该方法内不能使用this.setState进行渲染(反正也无效)

  • render: 不解释了

  • componentDidUpdate: 在DOM已经彻底渲染完成后,触发.

State Changes

状态属性的改变实际上和Props的流程差很少,只是是少了ComponentWillReciveProps方法.即,流程为:

  • shouldComponentUpdate: 检测是否组件须要从新渲染. 实际上就是经过该方法决定, render 方法是否能够直接跳过

  • componentWillUpdate: 新的props和state会被接收. 而且在该方法内不能使用this.setState进行渲染(反正也无效)

  • render: 不解释了

  • componentDidUpdate: 在DOM已经彻底渲染完成后,触发.

lifecycle有什么用

上面说了这么多方法, 那这些方法究竟是写在哪里的呢?
~~ 只能写在你的class UI中.
如今,咱们要在UI渲染完成时, 弹出一个提示框,说明完成。
so how to do?
很简单.看一下代码.

class Search extends Component{
    render(){
        return(
            <div>
            </div>
            )
    }
    componentDidMount(){
        alert('finish');
    }
}

这下, 应该懂了. 这里大体了解一下就行, 当作铺垫.

immutable state

由于state是起到组件渲染的关键做用. 因此, 通常外部的data都是存储在state当中, 而这样方式,即容易让你不由自主的改动this.state中的属性. 这样很容易,形成你直接改动this.state状态会无效, 以及会下降React内部对状态渲染的性能.
因此, 建议就是,若是须要改动,请直接所有替换掉.
若是涉及到Object, 则可使用Object.assign 或者 filter,map等方法 copy一份.

let newObj = Object.assign({},this.state.male,this.state.female);
let newArray = this.state.people.map((val)=>val);

不过,因为Object.assign支持度较低. 你能够本身手动造一个轮子.

Object.prototype.assign=function(origin,target){
    for(var i in target){
        if(origin.hasOwnProperty(i)){
            origin[i]=target[i];
        }
    }
}

或者可使用import "babel-polyfill"来作替代. 不过,这还有一个问题,就是深浅copy. 这里稍微提供点clue. 可使用 babel-polyfill 中的update方法, 该方法能够像mongoDB同样, 将更新事后的Object, deeply copy 一份给你. 这里就不赘述了,到时候google 一下即差很少了.

动画React

React为了方便动画开发, 特意提出了React CSSTransitionGroup这个addon. 细致点来讲, CSSTransitionGroup 只提供了3个效果-渲染, 新增,删除. 并且每一个特效归根结底,仍是须要你本身手动定义className, 他只是把className 的替换帮你作了.
so, 怎么用?
首先得下载npm:

npm install --save react-addons-css-transition-group
// 在js中引用
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

先看一个简单的demo. 这里也有线上demo:online demo

render(){
        let lis = this.state.num.map((i,index)=>(
                <li key={i} onClick={this.remove.bind(this,index)} >{i}</li>
            ));
        return(
            <ul>
                <CSSGroup transitionName="demo"
                        transitionEnterTimeout={300}
                        transitionLeaveTimeout={300}>
                {lis}
                </CSSGroup>
            </ul>
            )
    }

讲真,React会在真正渲染的时候,在他应用的位置添加span元素 而后进行class的替换. 固然,若是涉及到更加复杂的动画,就须要使用css3提供的transitionendanimationend来进行设置.
React一共提供了4个动画状态可供选择:

  • Appear: 当第一次加载节点时,能够进行的动画.

    • transitionAppear: 表示是否开启加载动画. 默认状况下是设置为false. 因此,若是你要时候, 须要手动开启transitionAppear={true}. 开启以后, 你就须要添加.name-appearname-appear-active的class 动画内容.

  • Enter: 当添加节点时,会触发添加动画.若是你使用的话,只须要设置.transitionEnterTimeout={timeout}便可。

    • transitionEnterTimeout: 用来设置节点添加动画持续的时间,不过, 你一样须要在class 中设置相同的transition时间. 若是时间不统一, 会以React设置为主.和Appear同样,也须要手动添加name-enter类名

  • Leave: 删除节点时, 触发的动画. 同上 enter. 须要手动添加transitionLeaveTimeout

这里提一下, 关于React class Name的设置位置. 只要和渲染节点设置在一块儿便可.
好比,上面的demo, 个人scss就能够设置为:

li {
        font-size: 15px;
        line-height: 24px;
        list-style-position: inside;
        list-style-type: disc;
        text-align: left;
        width: 80%;
        border: 1px solid;
        margin-top: 8px;
        &.demo-leave {
            opacity: 1;
            transform: translateX(0);
            &.demo-leave-active {
                opacity: 0;
                transform: translateX(250px);
                transition: 0.3s;
            }
        }
    }
相关文章
相关标签/搜索