react 快速入门

@eyasliu 2016-06-19 14:40:17发表于 eyasliu/blog react前端

React是Facebook开源的一个用于构建用户界面的Javascript库,专注于MVC架构中的V,即视图。

组件

我们可以创建一个有特殊功能的组件,在需要的地方可以反复的用。在编写应用的时候,我们是编写一个又一个的组件,然后组合成一个完整应用。

定义组件

继承 React 的 Component 类可以创建一个组件

class Hello extends React.Component{
  constructor(props, context){
    super()
    this.state = {} // 定义组件状态
  }

  render(){ // render 必须,渲染组件的html结构
    return <div></div>
  }
}

如果一个组件不需要使用状态,可以以函数的方式编写组件

const Hello = (props, context) => {
  return <div></div>
}

const Hello2 = props => <div></div>

JSX

JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。React 可以用来做简单的 JSX 句法转换。目前babel可以转换 JSX 语法为 JavaScript

JSX 是一个可选工具,目的是为了方便的书写HTMl与布局

基本语法

  • 组件名的首字母必须大写
  • 如果是渲染组件,组件名的变量名必须在作用域范围内
  • 根节点必须只有一个
  • 标签必须有闭合
  • 属性表达式:把表达式用大括号 {} 包起来,不要用引号 ""
  • 子节点:XML格式包围子节点
  • 注释:作为子节点,用 {} 包围注释部分
  • 判断:只能使用三元运算符做判断
  • 循环:不支持循环,只能使用遍历
var Nav = props => <div class="navbar"></div> // 组件名首字母大写
var myNavbar = <Nav color="blue" /> // Nav 变量必须在当前作用域
var myElement = <h1 className={"hello" + "demo"}>Hello {name}</h1> // 属性表达式
var myHello = <h1>hello {name ? 'world' : name}</h1> // 判断

var Comment => props => (
  <div>
    {// 这是单行注释}
    {/* 这是多行注释 */}
    hello
  </div>
)

var Each = <div>{[1,2,3].map(item => <span>{item}</span>)}</div> // 遍历

自定义属性

JSX 默认会转译所有字符串,防止各种 XSS 攻击

<div>{'First &middot; Second'}</div>

万不得已,可以直接使用原始 HTML。

<div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />

如果往原生 HTML 元素里传入 HTML 规范里不存在的属性,React 不会显示它们。如果需要使用自定义属性,要加 data- 前缀

<div data-custom-attribute="foo" />

css 类名的 class ,和 label 的 for 属性,都是js的关键字,不能用于属性名,所以使用 classNamehtmlFor 代替

<div className="myclass"></div>
<label htmlFor="demo"></label>

属性 props

组件对外公开一个简单的属性(Props)来实现功能,但内部细节可能有非常复杂的实现。组件要将数据传递给子组件,使用组件属性的形式传递下去,在子组件通过 this.props 访问传递的属性。绝对不能手动更改 props值

class Hello extends React.Component{
  render(){
    return <div>Hello {this.props.name}</div>
  }
}

<Hello name="Tenmic"></Hello>

props 验证

参考文档 http://reactjs.cn/react/docs/reusable-components.html

React.PropTypes 提供很多验证器来验证传入数据的有效性。当向 props 传入无效数据时,JavaScript 控制台会抛出警告

在组件内部定义静态变量 propTypes 可设置

class Hello extends React.Component{
  static propTypes = {
    name: React.PropTypes.string // name 必须为字符串
  }
  render(){
    return <div>Hello {this.props.name}</div>
  }
}

默认props

设置静态变量 defaultProps 设置默认的 props

class Hello extends React.Component{
  static defaultProps = {
    name: 'Tenmic'
  }
  render(){
    return <div>Hello {this.props.name}</div>
  }
}

状态 state

大部分组件的工作应该是从 props 里取数据并渲染出来。但是,有时需要对用户输入、服务器请求或者时间变化等作出响应,需要使用 state ,表示组件的不同状态。

State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据

  • 定义状态在组件的构造方法中定义state变量
  • 修改状态,只能通过 setState 方法
  • 只要修改状态,就会触发组件的重渲染
class Sidebar extends React.Component{
  constructor(){
    super();
    this.state = {open: false}
  }
  toggle(){
    this.setState({
      open: !this.state.open
    })
  }
  render(){
    return <div 
      className={this.state.open ? 'active' : ''
      onClick={this.toggle}
      }></div>
  }
}

生命周期

在组件的调用到销毁的过程中,会触发不同阶段的声明周期,

componentWillMount

整个周期只调用一次,在初始化渲染执行之前立刻调用

componentDidMount

在初始化渲染执行之后立刻调用一次,在生命周期中的这个时间点,组件拥有一个 DOM 展现

componentWillReceiveProps

在组件接收到新的 props 的时候调用。在初始化渲染的时候,该方法不会调用,只会在发生重渲染时调用参数 nextProps 获取即将传递过来的 props

shouldComponentUpdate

在接收到新的 props 或者 state,将要渲染之前调用。该方法在初始化渲染的时候不会调用,根据返回值决定组件是否需要更新

componentWillUpdate

在接收到新的 props 或者 state 之前立刻调用,在初始化渲染的时候该方法不会被调用。

使用该方法做一些更新之前的准备工作。

componentDidUpdate

在组件的更新已经同步到 DOM 中之后立刻被调用。该方法不会在初始化渲染的时候调用。

使用该方法可以在组件更新之后操作 DOM 元素

componentWillUnmount

在组件从 DOM 中移除的时候立刻被调用。

在该方法中执行任何必要的清理,比如无效的定时器,或者清除在 componentDidMount 中创建的 DOM 元素。

refs

为了方便的获取组件渲染后的DOM节点,可使用 ref,this.refs 存储了组件内所有的ref

class Sidebar extends React.Component{
  constructor(){
    super();
    this.state = {open: false}
  }
  toggle(){
    console.log(this.refs.sidebar)
  }
  render(){
    return <div ref="sidebar" onClick={this.toggle}></div>
  }
}

事件系统

事件处理器将会传入虚拟事件对象的实例,一个对浏览器本地事件的跨浏览器封装。它有和浏览器本地事件相同的属性和方法,包括 stopPropagation() 和 preventDefault(),但是没有浏览器兼容问题。

支持的事件: http://reactjs.cn/react/docs/events.html

事件绑定

听过在标签中设置 on + 事件名 可设置事件处理函数

class Sidebar extends React.Component{
  constructor(){
    super();
    this.state = {open: false}
  }
  toggle(event){
    console.log(event)
  }
  render(){
    return <div onClick={this.toggle}></div>
  }
}

context

为了方便的将数据传递给子组件,使用context将数据传递给所有的后代组件

定义传递的数据

在父组件,内部定义 childContextTypes,定义传递那些变量以及什么数据类型

class App extends React.Component{
  static childContextTypes = {
    name: React.PropTypes.string
  }
  // other code
}

getChildContext 函数返回需要传递的具体数据

class App extends React.Component{
  static childContextTypes = {
    name: React.PropTypes.string
  }
  getChildContext(){
    return {
      name: 'Tenmic'
    }
  }

  // other code

}

子组件获取数据

在子组件,通过定义 contextTypes 定义需要哪些值,然后通过 this.context 访问

class ChildComp extends React.Component{
  static contextTypes = {
    name: React.PropTypes.string
  }

  render(){
    this.context.name // 'Tenmic' ,从父组件获取,
  }
}

样式

在 React 中,行内样式并不是以字符串的形式出现,而是通过一个特定的样式对象来指定。在这个对象中,key 值是用驼峰形式表示的样式名,而其对应的值则是样式值,通常来说这个值是个字符串

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

React.render(<div style={divStyle}>Hello World!</div>, mountNode);

样式的 key 用驼峰形式表示,是为了方便与JS中通过DOM节点获取样式属性的方式保持一致