Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 最佳实践 #1

Closed
jianghai opened this issue Mar 3, 2016 · 1 comment
Closed

React 最佳实践 #1

jianghai opened this issue Mar 3, 2016 · 1 comment

Comments

@jianghai
Copy link
Owner

jianghai commented Mar 3, 2016

团队开始使用 React 后,不同的人写出的代码还真是千差万别。这里总结一些最佳实践(对比反模式),让团队有个参照。

杜绝不必要的 DOM 操作

例如我们要获取当前点击的 ID,jQuery 写多的人可能思维还没有转换过来,我要拿到这个元素,个元素,元素。。。

反模式

const App = React.createClass({

  getInitialState: {
    return {
      items: [{id: 1, name: 'one'}, {id: 2, name: 'two'}]
    }
  },

  handleClick(e) {
    console.log(e.target.getAttribute('data-id'))
  },

  render() {
    return (
      <ul>
        {this.state.items.map(item => {
          return <li key={item.id} data-id={item.id} onClick={this.handleClick}>{item.name}</li>
        })}
      </ul>
    )
  }
})

操作 DOM,即 JS 和 DOM 之间的通信耗费的资源比较大,既要给元素写数据,又要从元素中读取数据。而熟悉 React 的都知道,状态(state/props)决定了 UI 的最终呈现,状态跟 DOM 之间形成一种有序的对应关系,所以只需要知道当前点击的索引即可拿到对应的数据。

最佳实践

const App = React.createClass({

  getInitialState: {
    return {
      items: [{id: 1, name: 'one'}, {id: 2, name: 'two'}]
    }
  },

  handleClick(i) {
    console.log(this.state.items[i].id)
  },

  render() {
    return (
      <ul>
        {this.state.items.map((item, i) => {
          return <li key={item.id} onClick={this.handleClick.bind(this, i)}>{item.name}</li>
        })}
      </ul>
    )
  }
})

巧妙的利用 bind 方法绑定额外的参数,操作过程跟 DOM 毫无关系,自然和谐。

render 方法保持纯粹,避免一些跟 UI 呈现无关的处理逻辑

state 和 props 的变化会重新执行一次 render(除非 shouldComponentUpdate 返回 false),如果 render 里的一些逻辑跟 DOM 结构无关,则用 state 保持,避免不必要的性能消耗。

反模式

const App = React.createClass({

  getInitialState: {
    return {
      items: [{id: 1, name: 'one'}, {id: 2, name: 'two'}],
      index: 0
    }
  },

  handleClick(index) {
    this.setState({index})
  },

  render() {
    const url = '/data/test.do?index=' + this.state.index
    return (
      <ul url={url}>
        {this.state.items.map((item, i) => {
          return <li key={item.id} onClick={this.handleClick.bind(this, i)}>{item.name}</li>
        })}
      </ul>
    )
  }
})

最佳实践

const App = React.createClass({

  getInitialState: {
    return {
      items: [{id: 1, name: 'one'}, {id: 2, name: 'two'}],
      url: '/data/test.do?index=0'
    }
  },

  handleClick(index) {
    this.setState({url: '/data/test.do?index=' + index})
  },

  render() {
    return (
      <ul url={this.state.url}>
        {this.state.items.map((item, i) => {
          return <li key={item.id} onClick={this.handleClick.bind(this, i)}>{item.name}</li>
        })}
      </ul>
    )
  }
})

url 只是一种数据,跟具体的 DOM 结构无关,所以可以抽离出来处理,提升 render 的处理速度。

属性验证

完整的属性验证既能检查外部传入的数据(不可控因素),减少出错后查找 bug 所耗费的时间,又能让人一目了然了解组件所有对外的接口。

最佳实践

import React, { PropTypes } from 'react'

const MyComponent = React.createClass({
  propTypes: {
    items: PropTypes.array.isRequired,
    onChange: PropTypes.fun
  }
})
@jianghai
Copy link
Owner Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant