前端之React实战-交互与动态UI

Interactivity and Dynamic UIs

React.findDOMNode()

组件并非真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫作虚拟 DOM (virtual DOM)。只有当它插入文档之后,才会变成真实的 DOM 。根据 React 的设计,全部的 DOM 变更,都先在虚拟 DOM上发生,而后再将实际发生变更的部分,反映在真实 DOM上,这种算法叫作 DOM diff ,它能够极大提升网页的性能表现。可是,有时须要从组件获取真实 DOM 的节点,这时就要用到 React.findDOMNode 方法。javascript

var MyComponent = React.createClass({
  handleClick: function() {
    React.findDOMNode(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>
    );
  }
});

React.render(
  <MyComponent />,
  document.getElementById('example')
);

须要注意的是,因为 React.findDOMNode 方法获取的是真实 DOM ,因此必须等到虚拟 DOM 插入文档之后,才能使用这个方法,不然会返回 null 。上面代码中,经过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件以后,才会调用 React.findDOMNode 方法。css

getInitialState

设置State的初始状态。html

var MyComponent = React.createClass({
    getInitialState: function(){
        return {
            count: 5
        }
    },
    render: function(){
        return (
            <h1>{this.state.count}</h1>
        )
    }
});

Style

参考资料java

  • React行内样式最佳实践react

Inline-style

在React中,若是要使用行内元素,不能够直接使用style="”这种方式,能够有:git

import React from 'react';

var style = {
  backgroundColor: '#EEE'
};

export default React.createClass({
  render: function () {
    return (
      <div style={style}>
      //或者<div style={{backgroundColor: '#EEE'}}>
        <h1>Hello world</h1>
      </div>
    )
  }
});

能够看出,React的style属性接收的也是一个JavaScript对象。github

Class

你能够根据这个策略为每一个组件建立 CSS 文件,可让组件名和 CSS 中的 class 使用一个命名空间,来避免一个组件中的一些 class 干扰到另一些组件的 class。算法

app/components/MyComponent.cssapi

.MyComponent-wrapper {
  background-color: #EEE;
}

app/components/MyComponent.jsx浏览器

import './MyComponent.css';
import React from 'react';

export default React.createClass({
  render: function () {
    return (
      <div className="MyComponent-wrapper">
        <h1>Hello world</h1>
      </div>
    )
  }
});

Multiple Class

上文中说起的利用className方式赋值,若是在存在多个类名的状况下:

render: function() {
  var cx = React.addons.classSet;
  var classes = cx({
    'message': true,
    'message-important': this.props.isImportant,
    'message-read': this.props.isRead
  });
  // same final string, but much cleaner
  return <div className={classes}>Great, I'll be there.</div>;
}

Event

React对于事件的支持很是完善,能够查看这里。React 实现了一个“合成事件”层(synthetic event system),这个事件模型保证了和 W3C 标准保持一致,因此不用担忧有什么诡异的用法,而且这个事件层消除了 IE 与 W3C 标准实现之间的兼容问题。“合成事件”额外提供了两个好处:自动绑定上下文和事件委托

  • “合成事件”自动将事处理件方法的上下文绑到当前组件,因此 handleClick 方法里面能够直接使用this.setState

  • “合成事件”会以事件委托(event delegation)的方式绑定到组件最上层,而且在组件卸载(unmount)的时候自动销毁绑定的事件。

固然,在React中,也可使用原生事件,好比你在 componentDidMount 方法里面经过 addEventListener 绑定的事件就是浏览器原生事件。使用原生事件的时候注意在 componentWillUnmount 解除绑定 removeEventListener。全部经过 JSX 这种方式绑定的事件都是绑定到“合成事件”,除非你有特别的理由,建议老是用 React 的方式处理事件。

Event Bind

最基本的绑定方式就是依靠相似于onClick={handleClick}的方式,要注意,这里不一样于ng-click,onClick传递的参数只能是一个方法,而不能是一个调用。若是要简单来写的话能够采Lambda表达式的方式:

onClick={()=>{alert(1);}}

Event Params

给事件处理函数传递额外参数的方式:bind(this, arg1, arg2, ...)

render: function() {
    return <p onClick={this.handleClick.bind(this, 'extra param')}>;
},
handleClick: function(param, event) {
    // handle click
}

由上面能够看出,Event通常都是做为最后一个参数传递到handleClick中,这里的event是SyntheticEvent对象,它的主要属性以下:

boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent
void preventDefault()
void isDefaultPrevented()
void stopPropagation()
void isPropagationStopped()
DOMEventTarget target
number timeStamp
string type

List Element

在React中,也会常常遇到须要为某个群组绑定事件的状况,能够参考以下代码:

var GroceryList = React.createClass({
  handleClick: function(i) {
    console.log('You clicked: ' + this.props.items[i]);
  },
  render: function() {
    return (
      <div>
        {this.props.items.map(function(item, i) {
          return (
            <div onClick={this.handleClick.bind(this, i)} key={i}>{item}</div>
          );
        }, this)}
      </div>
    );
  }
});
React.render(
  <GroceryList items={['Apple', 'Banana', 'Cranberry']} />, mountNode
);

TouchEvent

If you'd like to use React on a touch device such as a phone or tablet, simply call React.initializeTouchEvents(true); to enable touch event handling.

接口暴露

譬如在某个子组件中,提供了某个方法:

var ButtonComponent = React.createClass({
    getDragonKillingSword: function(){
        //送宝刀
    },
    render: function(){
        return (<button onClick={this.getDragonKillingSword}>屠龙宝刀,点击就送</button>);
    }
});

若是在父组件中想手动调用该方法,则能够利用ref方式:

var ImDaddyComponent = React.createClass({
  render: function(){
    return (
      <div>
        //其余组件
        <ButtonComponent />
        //其余组件
      </div>
    );
  }
});

在父组件的功能方程中:

this.refs.getSwordButton.getDragonKillingSword();

反之,若是须要在子组件中调用父组件的方法,则能够直接将父组件的方法做为Props参数传入到子组件中:

<ButtonComponent clickCallback={this.getSwordButtonClickCallback}/>

Ajax

组件的数据来源,一般是经过 Ajax 请求从服务器获取,能够在componentDidMount 方法中设置 Ajax 请求,等到请求成功,再用 this.setState 方法从新渲染 UI。

var UserGist = React.createClass({
      getInitialState: function() {
        return {
          username: '',
          lastGistUrl: ''
        };
      },

      componentDidMount: function() {
        $.get(this.props.source, function(result) {
          var lastGist = result[0];
          if (this.isMounted()) {
            this.setState({
              username: lastGist.owner.login,
              lastGistUrl: lastGist.html_url
            });
          }
        }.bind(this));
      },

      render: function() {
        return (
          <div>
            {this.state.username}'s last gist is
            <a href={this.state.lastGistUrl}>here</a>.
          </div>
        );
      }
    });

    React.render(
      <UserGist source="https://api.github.com/users/octocat/gists" />,
      document.body
    );

不过笔者习惯仍是将整个获取数据,处理数据的业务逻辑放在Angular中进行。

相关文章
相关标签/搜索