reactjs的一些笔记

 

1.使用虚拟DOM作为其不同的实现。同时可以由服务器node.js渲染,从而不需要过重的浏览器DOM支持。

 
2.虚拟DOM:在浏览器端用javascript实现了一套DOM API。用react开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,react都会重新构建整个DOM树,然后将当前整个DOM树和上一次的进行对比,得到区别后,仅仅将需要变化的部分进行实际浏览器的DOM树更新。从而使程序员只需要关心数据整体,两次数据之间的UI如何变化,就交给框架去做。
 
3. React 独有的 JSX 语法,跟 JavaScript 不兼容凡是使用 JSX 的地方,都要加上 type="text/jsx" 。 其次,React 提供两个库: react.js 和 JSXTransformer.js ,它们必须首先加载。其中,JSXTransformer.js 的作用是将 JSX 语法转为 JavaScript 语法。这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。
 
4.一个最基本的react组件
    var Greet = React.createClass({
            render:function(){
                return <h1>Hello {this.props.name}</h1>;
            }
        });
        React.render(
            <Greet name="Jack" />,
            document.getElementById('container')
        );
有几点需要注意:

 1)获取属性的值用的是this.props.属性名

 2)创建的组件名称首字母必须大写。

 3)为元素添加css的class时,要用className。

 4)组件的style属性的设置方式也值得注意,要写成style={{width: this.state.witdh}}。这是因为 React 组件样式是一个对象,所以第一重大括号表示这是 JavaScript 语法,第二重大括号表示样式对象。

 

 

5.组件状态

    react将组件看做一个状态机,一旦组件的状态发生改变,react就会触发重新渲染UI(自动调用this.render)。通过this.state.XX来定义和设置用户自定义的状态。而getInitialState函数则是在组件初始化时执行,返回null或一个对象。例:

     var InputState = React.createClass({

            getInitialState:function(){

                return {enable:false};

            },

            handleClick:function(event){

                this.setState({enable:!this.state.enable});

            },

            render:function(){

                return (

                    <p>

                        <input type="text" disabled={this.state.enable} />

                        <button onClick={this.handleClick}>Change State</button>

                    </p>

                );

            }

        });

 这里值得注意的几点如下:

 1)getInitialState函数必须有返回值,可以是NULL或者一个对象。

 2)访问state的方法是this.state.属性名。

 3)变量用{}包裹,不需要再加双引号。

 

6.react组件的生命周期有3个    

  • Mounting:已插入真实 DOM

  • Updating:正在被重新渲染

  • Unmounting:已移出真实 DOM

     

     每个状态都有两种处理函数,will在进入状态前执行,did在进入之后执行,共五种处理函数: 

  • componentWillMount()

  • componentDidMount()

  • componentWillUpdate(object nextProps, object nextState)

  • componentDidUpdate(object prevProps, object prevState)

  • componentWillUnmount()

 

   此外,react还提供2种特殊状态的处理函数:
  • componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用

  • shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用

     

 

 

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

这里需要注意, this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。

React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object。更多的 React.Children 的方法,请参考

https://facebook.github.io/react/docs/top-level-api.html#react.children

 

8.组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。

组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求

 

var MyTitle = React.createClass({
  propTypes:{
    title: React.PropTypes.string.isRequired,},

  render:function(){return<h1>{this.props.title}</h1>;}});

这样,就规定了MyTitle的title属性是必须的,且类型为字符串。如果不符合要求,控制台就会报错。

 

更多的PropTypes设置,可以查看官方文档

此外,getDefaultProps 方法可以用来设置组件属性的默认值。

 

getDefaultProps :function(){return{
      title :'Hello World'};},
 

 

9.组件并不是真实的DOM节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM 。

但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性

 

var MyComponent = React.createClass({
  handleClick:function(){
    this.refs.myTextInput.focus();},
  render:function(){return(<div><input type="text" ref="myTextInput"/><input type="button" value="Focus the text input" onClick={this.handleClick}/></div>);}});

 

文本输入框有一个 ref 属性,然后 this.refs.[refName] 就会返回这个真实的 DOM 节点。需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性。

 

10.组件的构造规则跟函数或者对象的构造规则有异曲同工之妙,最大的共同点就是单一功能原则,即一个组件应该尽量只做一件事情,如果它的功能逐渐扩大就需要被拆分为更小的子组件。

 
11.判断数据是否是state的方法:
    (1)是否是从父级通过props传入的?如果是,可能不是state。
    (2)是否会随着时间改变?如果不是,可能不是state。
    (3)能根据组件中其它state数据或者props计算出来吗?如果是,就不是state。
 
12.如何判断哪些组件应该拥有哪些state?

 

 

13.常用的通知React 数据变化的方法是调用 setState(data, callback) 。这个方法会合并(merge) data 到 this.state,并重新渲染组件。渲染完成后,调用可选的callback 回调。大部分情况下不需要提供 callback ,因为 React 会负责把界面更新到最新状态。尝试把尽可能多的组件无状态化。 这样做能隔离 state,把它放到最合理的地方,也能减少冗余并,同时易于解释程序运作过程。常用的模式是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 props 传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。

 
14.
 

 
 

15.如果子级要在多个渲染阶段保持自己的特征和状态,在这种情况下,你可以通过给子级设置惟一标识的 key 来区分。当 React 校正带有 key 的子级时,它会确保它们被重新排序(而不是破坏)或者删除(而不是重用)。 务必把 key 添加到子级数组里组件本身上,而不是每个子级内部最外层 HTML 上。

 
16.有时候为了控制性能,需要在数据变化后不更新界面,这种情况下,可以重写shouldComponetUpdate()方法使其返回false来让react跳过对子树的处理。    
        注: 如果在数据变化时让 shouldComponentUpdate() 返回 false,React 就不能保证用户界面同步 。当使用它的

 

时候一定确保你清楚到底做了什么,并且只在遇到明显性能问题的时候才使用它。不要低估 JavaScript 的速

度,DOM 操作通常才是慢的原因。

 

 

17. 传递Props的技巧,如果想把传入组件的全部props复制到对应的HTML元素上,<a {...this.props}>即可。有时候不需要传递所有属性,可使用 var { checked, ...other } = this.props; 再调用other即代表除了checked以外所有的props,而checked就是this,props.checked,可以直接使用,多个属性可以用逗号隔开。如果不使用 JSX,可以使用一些库来实现相同效果。Underscore 提供 _.omit 来过滤属性, _.extend 复制属性到新的对象。P60

 

var FancyCheckbox = React.createClass(

 

    render: function() {

 

        var checked = this.props.checked;

 

        var other = _.omit(this.props, 'checked');

 

        var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';

 

        return (

 

            React.DOM.div(_.extend({}, other, { className: fancyClass }))

 

        );

 

    }

 

});

 

 


 

 

 

18.propTypes的用法,见P52,限制props的类型。也可以限制children的个数。
 
19.有时一些复杂的组件需要公用一些功能,类似跨切面关注点,react里使用mixins来解决这类问题。P55
     例如: 一个组件需要定期更新。用 setInterval() 做很容易,但当不需要它的时候取消定时器来节省内存是非常重要的。
                       
 
 
20.设置了 value 的 是一个受限组件。 对于受限的 ,渲染出来的 HTML 元素始终保持 value属性的值。要想改变就需要使用onChange事件。如果既想给组件赋一个初始值,又想反应用户对组件值的改变,可以设置defaultValue,同理,类型为radio 、 checkbox 的 支持 defaultChecked 属性,支持 defaultValue 属性  
 
21.React中<select>元素设置选中使用value属性,而不是option的select属性。
 
22.为了和浏览器交互,有时候需要对DOM节点的引用,使用refs和getDOMNode()即可,注意只有在组件已经放进了DOM中时,此方法才有用。
 
23.组件的生命周期
     React组件的生命周期主要包括 挂载更新移除 三个部分。
        挂载期函数: 
            (1)getInitialState(): object 在组件被挂载之前调用。状态化的组件应该实现这个方法,返回初始的state数据。
 
            (2)componentWillMount() 在挂载发生之前立即被调用。
            (3)componentDidMount() 在挂载结束之后马上被调用。需要DOM节点的初始化操作应该放在这里。
 
        更新期函数:
            (1)componentWillReceiveProps(object nextProps) 当一个挂载的组件接收到新的props的时候被调用。该方法应该用于比较this.props 和 nextProps ,然后使用 this.setState() 来改变state。
            (2)shouldComponentUpdate(object nextProps, object nextState): boolean 当组件做出是否要更新DOM决定的时候被调用。实现该函数,优化 this.props 和 nextProps ,以及 this.state 和 nextState 的比较,如果不需要React更新DOM,则返回false。
            (3)componentWillUpdate(object nextProps, object nextState) 在更新发生之前被调用。你可以在这里调用 this.setState()。
            (4)componentDidUpdate(object prevProps, object prevState) 在更新发生之后调用。
 
        移除期函数:
            (1)componentWillUnmount() 在组件移除和销毁之前被调用。清理工作应该放在这里。
 
 
 
 
        
 
24.shouldComponentUpdate()更新原理:
    
 
 
 
    详情见P74
 
 
25. Immutable-js
 
immutable-js提供了通过结构性共享一成不变持久化集合。让我们看看这些性能:

 

        • 不可变的:一旦创建,集合不能在另一个时间点改变。

        • 持久性:新的集合可以由从早先的集合和突变结合创建。在创建新的集合后,原来集合仍然有效。

        • 结构共享:使用新的集合创建为与对原始集合大致相同的结构,减少了拷贝的最低限度,以实现空间效率和可接受的性能。如果新的集合等于原始的集合,则通常会返回原来的集合。

 

   

     不变性使得跟踪更改方便;而变化将总是产生在新的对象,所以我们只需要检查的已经改变参考对象。

    即原始的对象是不变的,每当对原始数据进行改变,会创建一个新的对象。

    例:           

            var SomeRecord = Immutable.Record({ foo: null });
            var x = new SomeRecord({ foo: 'bar' });
            var y = x.set('foo', 'baz');
            x === y; // false

 

26.  React API

    (1)React.createClass  不再赘述。

    (2)React.createElement:

                    

 

 

            ReactElement createElement(
                string/ReactClass type,
                [object props],
                [children ...]
            )

            创建并返回一个新的指定类型的 ReactElement。type 参数可以是一个 html 标签名字字符串(例如,“div”,“span”,等等),或者是 ReactClass (通过 React.createClass 创建的)。

 

 

 

 

 

 

 
 
    (3)React.createFactory:

 

           

            factoryFunction createFactory(
                string/ReactClass type
            )

            返回一个生成指定类型 ReactElements 的函数。比如 React.createElement,type 参数可以是一个 html 标签名字字符串(例如,“div”,“span”,等等),或者是 ReactClass 。

 
 
    (4) boolean unmountComponentAtNode(DOMElement container)

 

            从 DOM 中移除已经挂载的 React 组件,清除相应的事件处理器和 state。如果在 container 内没有组件挂 载,这个函数将什么都不做。如果组件成功移除,则返回 true ;如果没有组件被移除,则返回 false 。

 
 
    (5)string renderToString(ReactElement element)

 

            把组件渲染成原始的 HTML 字符串。该方法应该仅在服务器端使用。React 将会返回一个 HTML 字符串。你可以在服务器端用此方法生成 HTML,然后将这些标记发送给客户端,这样可以获得更快的页面加载速度,并且有利于搜索引擎抓取页面,方便做 SEO。

 

    (6) string renderToStaticMarkup(ReactElement element)

 

            和 renderToString 类似,除了不创建额外的 DOM 属性,例如 data-react-id ,因为这些属性仅在 React 内部使用。如果你想用 React 做一个简单的静态页面生成器,这是很有用的,因为丢掉额外的属性能够节省很多字节。

 

    (7)React.isValidElement

 

            boolean isValidElement(* object)判断对象是否是一个 ReactElement。

 

    (8)initializeTouchEvents(boolean shouldUseTouch)

 

            配置 React 的事件系统,使 React 能处理移动设备的触摸( touch )事件。

    

    (9)React.ChildrenReact.Children

 

            React.Children 为处理 this.props.children 这个封闭的数据结构提供了有用的工具。

            详情见P82,有.map 、.forEach、.count、.only等用法。

 

    27.ReactComponent    

            React 组件实例在渲染的时候创建。这些实例在接下来的渲染中被重复使用,可以在组件方法中通过 this 访问。唯一一种在 React 之外获取 React 组件实例句柄的方式就是保存 React.render 的返回值。在其它组件内,可以使用 refs 得到相同的结果。

            

    (1)setState(object nextState[, function callback]))

 

 

 

            合并 nextState 和当前 state。这是在事件处理函数中和请求回调函数中触发 UI 更新的主要方法。另外,也支持可选的回调函数,该函数在 setState 执行完毕并且组件重新渲染完成之后调用。

 

 

            注:setState() 不会立刻改变 this.state ,而是创建一个即将处理的 state 转变。在调用该方法之后获取 this.state 的值可能会得到现有的值,而不是最新设置的值。   
        

    (2)replaceState(object nextState[, function callback])类似于 setState(),但是删除之前所有已存在的 state 键,这些键都不在 nextState 中。

 

    

    (3)forceUpdate([function callback])

            如果 render() 方法从 this.props 或者 this.state 之外的地方读取数据,你需要通过调用 forceUpdate() 告诉 React 什么时候需要再次运行 render()。如果直接改变了 this.state ,也需要调用 forceUpdate()。

            注:应该尽量避免使用forceUpdate的情况。

    

    (4)bool isMounted()

 

            如果组件渲染到了 DOM 中, isMounted() 返回 true。可以使用该方法保证 setState() 和 forceUpdate() 在异步场景下的调用不会出错。

 

    (5)

 

28.render() 函数应该是纯粹的,也就是说该函数不修改组件 state,每次调用都返回相同的结果,不读写 DOM 信息,也不和浏览器交互(例如通过使用 setTimeout )。如果需要和浏览器交互,在 componentDidMount()中或者其它生命周期方法中做这件事。保持 render() 纯粹,可以使服务器端渲染更加切实可行,也使组件更容易被理解。

 

 

 

 

 

 

 

 

 

29.object statics

 

        statics 对象允许你定义静态的方法,这些静态的方法可以在组件类上调用。

 

30. React 也提供了一些 DOM 里面不存在的属性。

 

 

        • key :可选的唯一的标识器。当组件在 渲染 过程中被各种打乱的时候,由于差异检测逻辑,可能会被销毁后重新创建。给组件绑定一个 key,可以持续确保组件还存在 DOM 中。 

 

        • ref:参考这里 (页 0)

        • dangerouslySetInnerHTML :提供插入纯 HTML 字符串的功能,主要为了能和生成 DOM 字符串的库整合。

 

 

31.React的渲染策略

    (1)若前后两个节点元素或者组件的类型不同,React会直接把他们当做不同的子树,甚至不会尝试计算出该渲染什么,直接从DOM中移除之前的节点,然后插入新的节点。

    (2)比较两个DOM节点的时候,查看两者的属性,然后找出变化的属性。

    (3)对于自定义组件,React决定2个自定义组件是相同的,利用新组件上的所有属性,然后再之前的组件实例上调用componetWill(Did)ReceiveProps()。现在,之前的组件的render(0被调用,然后差异算法重新比较新的状态和上一次的状态。

    (4)为了完成子级更新,React同时遍历两个子级列表,当发现差异的时候,就产生一次DOM修改。        

            在开始处插入元素比较麻烦。React 发现两个节点都是 span,因此直接修改已有 span 的文本内容,然后在后面插入一个新的 span 节点。

                renderA:<div><span>first</span></div>

                renderB:<div><span>secon</span><span>first</span></div>
            => [replaceAttribute textContent 'second'], [insertNode <span>first</span>]

        为了解决这个问题,引入了一个可选的属性keys。如果指定了一个键值,React 就能够检测出节点插入、移除和替换,并且借助哈希表使节点移动复杂度为O(n)。

        注:键值只需要在兄弟节点中唯一,而不是全局唯一。

        

32.行内样式:    

    var divStyle = {
        color: 'white',
        backgroundImage: 'url(' + imgUrl + ')',
        WebkitTransition: 'all', // 注意这里的首字母'W'是大写
        msTransition: 'all' // 'ms'是唯一一个首字母需要小写的浏览器前缀
    };

    React.render(Hello World!, mountNode);

 

33.通常,一个组件的子代(this.props.children)是一个组件的数组,即为数组类型,但是当只有一个子代的时候,this.props.children是一个单独的组件,而不是数组形式,这样就减少了数组的占用。

 

 

 

 

 

 

34.getInitialState里的props是一个反模式。详情见P118。

 

35.给DOM元素绑定React未提供的事件,比如想共用react和jquery的时候,在componentDidMount中 调用  

 

component.addEventListener('xxx', this.handleResize) 绑定事件,在componentWillUnmount中removeEventListener()取消绑定。详情见P120

 
36.在 componentDidMount 时加载数据。当加载成功,将数据存储在 state 中,触发 render 来更新你的 UI。

 

当执行同步请求的响应时,在更新 state 前, 一定要先通过 this.isMounted() 来检测组件的状态是否还是 mou

nted。

 

posted on 2016-06-21 15:40  夏尔先生  阅读(1490)  评论(0编辑  收藏  举报

导航