博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React模式【译】
阅读量:6454 次
发布时间:2019-06-23

本文共 6466 字,大约阅读时间需要 21 分钟。

原文:

代码结构

  • class definition

    • constructor

      • event handlers

    • 'component' lifecycle

    • getters

    • render

  • defaultProps

  • proptypes

class Person extends React.Component {  constructor (props) {    super(props);    this.state = { smiling: false };    this.handleClick = () => {      this.setState({smiling: !this.state.smiling});    };  }  componentWillMount () {    // add event listeners (Flux Store, WebSocket, document, etc.)  },  componentDidMount () {    // React.getDOMNode()  },  componentWillUnmount () {    // remove event listeners (Flux Store, WebSocket, document, etc.)  },  get smilingMessage () {    return (this.state.smiling) ? "is smiling" : "";  }  render () {    return (      
{this.props.name} {this.smilingMessage}
); },}Person.defaultProps = { name: 'Guest'};Person.propTypes = { name: React.PropTypes.string};

格式化属性

当有2个以上属性时,就换行显示

// bad
// good
// bad
// good

依赖属性

使用getters方法代替定义依赖属性

// bad  firstAndLastName () {    return `${this.props.firstName} ${this.props.lastname}`;  }  // good  get fullName () {    return `${this.props.firstName} ${this.props.lastname}`;  }

依赖状态

使用getters方法代替定义依赖状态,注意为了提高可读性需要在命名时加上一个动词前缀。

// badhappyAndKnowsIt () {  return this.state.happy && this.state.knowsIt;}
// goodget isHappyAndKnowsIt () {  return this.state.happy && this.state.knowsIt;}

这些方法必须返回boolean类型

用三元运算代替Sub-render方法

保证渲染逻辑都写在render方法里

// badrenderSmilingStatement () {  return {(this.state.isSmiling) ? " is smiling." : ""};},render () {  return 
{this.props.name}{this.renderSmilingStatement()}
;}
// goodrender () {  return (    
{this.props.name} {(this.state.smiling) ?
is smiling : null }
);}

视图组件

用定义的组件组成视图。不要创建混杂着布局和功能的一次性组件

// badclass PeopleWrappedInBSRow extends React.Component {  render () {    return (      
); }}
// goodclass BSRow extends React.Component {  render () {    return 
{this.props.children}
; }}class SomeView extends React.Component { render () { return (
); }}

容器组件(有状态组件)

容器组件负责获取数据并交付给相应的子组件渲染,仅此而已。— Jason Bonta

// bad// CommentList.jsclass CommentList extends React.Component {  getInitialState () {    return { comments: [] };  }  componentDidMount () {    $.ajax({      url: "/my-comments.json",      dataType: 'json',      success: function(comments) {        this.setState({comments: comments});      }.bind(this)    });  }  render () {    return (      
    {this.state.comments.map(({body, author}) => { return
  • {body}—{author}
  • ; })}
); }}
//good// CommentList.jsclass CommentList extends React.Component {  render() {    return (      
    {this.props.comments.map(({body, author}) => { return
  • {body}—{author}
  • ; })}
); }}// CommentListContainer.jsclass CommentListContainer extends React.Component { getInitialState () { return { comments: [] } } componentDidMount () { $.ajax({ url: "/my-comments.json", dataType: 'json', success: function(comments) { this.setState({comments: comments}); }.bind(this) }); } render () { return
; }}

相关链接:

render中缓存状态

不要在render中缓存状态

// badrender () {  let name = `Mrs. ${this.props.name}`;  return 
{name}
;}// goodrender () { return
{`Mrs. ${this.props.name}`}
;}
// bestget fancyName () {  return `Mrs. ${this.props.name}`;}render () {  return 
{this.fancyName}
;}

这里多半是出于代码风格的考虑,不过还是保持比较好,我怀疑也可能跟性能有关。

复合条件

不要把复合条件判断放在render里。

// badrender () {  return 
{if (this.state.happy && this.state.knowsIt) { return "Clapping hands" }
;}
// betterget isTotesHappy() {  return this.state.happy && this.state.knowsIt;},render() {  return 
{(this.isTotesHappy) && "Clapping hands"}
;}

这里最好的解决方案是使用容器组件来管理你的状态然后在通过属性(props)往下层传递。

检查空值

不要去检查是否存在某个prop值,快使用defaultProps

// badrender () {  if (this.props.person) {    return 
{this.props.person.firstName}
; } else { return null; }}
// goodclass MyComponent extends React.Component {  render() {    return 
{this.props.person.firstName}
; }}MyComponent.defaultProps = { person: { firstName: 'Guest' }};

当你的值是对象或者数组时,使用 PropTypes.shape声明嵌套数据的预期类型。

通过Props设置State

不要通过props值去设置state,除非明显是个初始值。

// badgetInitialState () {  return {    items: this.props.items  };}
// goodgetInitialState () {  return {    items: this.props.initialItems  };}

详细请阅读官网的

命名事件响应方法

// badpunchABadger () { /*...*/ },render () {  return 
;}
// goodhandleClick () { /*...*/ },render () {  return 
;}

处理方法的命名必须:

  • 第一个单词为handle

  • 最后一个单词为要响应的事件(比如Click,Change)

  • 现在时态

    如果为了避免命名冲突,你可以在handle和事件名中间加入其他信息。比如,你可以定义handleNameChange 和handleAgeChange来区分onChange的不同响应处理。不过当你这样做的时候,你要问问自己是否需要一个新的组件了。

命名事件

可以使用自定义事件替代预设的事件名。

class Owner extends React.Component {  handleDelete () {    // handle Ownee's onDelete event  }  render () {    return 
; }}class Ownee extends React.Component { render () { return
; }}Ownee.propTypes = { onDelete: React.PropTypes.func.isRequired};

使用PropTypes

使用PropTypes可以预先定义属性的类型,可以在之后获得一些有意义的警告信息。

MyValidatedComponent.propTypes = {  name: React.PropTypes.string};

MyValidatedComponentname属性值如果不是string类型的话, 会输出警告。

// Warning: Invalid prop `name` of type `number` supplied to `MyValidatedComponent`, expected `string`.

在这里也可以设置属性是否是必须存在的。

MyValidatedComponent.propTypes = {  name: React.PropTypes.string.isRequired}

这个组件会验证是否存在name属性。

// Warning: Required prop `name` was not specified in `Person`

相关链接:

使用特殊符号

要在使用React中使用特殊符号,请使用String.fromCharCode()

// bad
PiCO · Mascot
// nope
PiCO · Mascot
// good
{'PiCO ' + String.fromCharCode(183) + ' Mascot'}
// better
{`PiCO ${String.fromCharCode(183)} Mascot`}

相关链接:

Tables

浏览器认为你是愚蠢的,但是React不这么人为。请始终为你的table组件添加tbody。

// badrender () {  return (    
...
);}// goodrender () { return (
...
);}

浏览器会自动插入tbody当你忘了写它。React则不会,这样会给你的代码带来混乱,请记住使用tbody。

classnames

使用管理你的classes逻辑。

// badget classes () {  let classes = ['MyComponent'];  if (this.state.active) {    classes.push('MyComponent--active');  }  return classes.join(' ');}render () {  return 
;}
// goodrender () {  let classes = {    'MyComponent': true,    'MyComponent--active': this.state.active  };  return 
;}

相关链接:

转载地址:http://phfzo.baihongyu.com/

你可能感兴趣的文章
iOS项目分层
查看>>
UML关系图
查看>>
一个action读取另一个action里的session
查看>>
leetcode 175. Combine Two Tables
查看>>
如何给一个数组对象去重
查看>>
Guava包学习-Cache
查看>>
2019-06-12 Java学习日记之JDBC
查看>>
灯箱效果(点击小图 弹出大图集 然后轮播)
查看>>
linux c 笔记 线程控制(二)
查看>>
samba服务器配置
查看>>
vue.js笔记
查看>>
【Unity3D入门教程】Unity3D之GUI浅析
查看>>
Hive 简单操作
查看>>
湘潭1247 Pair-Pair(树状数组)
查看>>
IEnumerable<T>
查看>>
IntelliJ IDEA 注册码
查看>>
linux 上面配置apache2的虚拟目录
查看>>
Linux学习总结 (未完待续...)
查看>>
NoSQL数据库探讨 - 为什么要用非关系数据库?
查看>>
String字符串的截取
查看>>