资讯专栏INFORMATION COLUMN

React模式【译】

BicycleWarrior / 2686人阅读

摘要:检查空值不要去检查是否存在某个值,快使用。当你的值是对象或者数组时,使用声明嵌套数据的预期类型。命名事件可以使用自定义事件替代预设的事件名。

原文:react-patterns

代码结构

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方法代替定义依赖状态,注意为了提高可读性需要在命名时加上一个动词前缀。

// bad
happyAndKnowsIt () {
  return this.state.happy && this.state.knowsIt;
}
// good
get isHappyAndKnowsIt () {
  return this.state.happy && this.state.knowsIt;
}

这些方法必须返回boolean类型

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

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

// bad
renderSmilingStatement () {
  return {(this.state.isSmiling) ? " is smiling." : ""};
},

render () {
  return 
{this.props.name}{this.renderSmilingStatement()}
; }
// good
render () {
  return (
    
{this.props.name} {(this.state.smiling) ? is smiling : null }
); }
视图组件

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

// bad
class PeopleWrappedInBSRow extends React.Component {
  render () {
    return (
      
); } }
// good
class BSRow extends React.Component {
  render () {
    return 
{this.props.children}
; } } class SomeView extends React.Component { render () { return ( ); } }
容器组件(有状态组件)

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

// bad
// CommentList.js

class 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.js

class CommentList extends React.Component {
  render() {
    return (
      
    {this.props.comments.map(({body, author}) => { return
  • {body}—{author}
  • ; })}
); } } // CommentListContainer.js class 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 ; } }

相关链接:
Container Components
React.js Conf 2015 - Making your app fast with high-performance components

render中缓存状态

不要在render中缓存状态

// bad
render () {
  let name = `Mrs. ${this.props.name}`;

  return 
{name}
; } // good render () { return
{`Mrs. ${this.props.name}`}
; }
// best
get fancyName () {
  return `Mrs. ${this.props.name}`;
}

render () {
  return 
{this.fancyName}
; }

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

复合条件

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

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

render() {
  return 
{(this.isTotesHappy) && "Clapping hands"}
; }

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

检查空值

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

// bad
render () {
  if (this.props.person) {
    return 
{this.props.person.firstName}
; } else { return null; } }
// good
class MyComponent extends React.Component {
  render() {
    return 
{this.props.person.firstName}
; } } MyComponent.defaultProps = { person: { firstName: "Guest" } };

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

通过Props设置State

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

// bad
getInitialState () {
  return {
    items: this.props.items
  };
}
// good
getInitialState () {
  return {
    items: this.props.initialItems
  };
}

详细请阅读官网的Props in getInitialState Is an Anti-Pattern

命名事件响应方法
// bad
punchABadger () { /*...*/ },

render () {
  return 
; }
// good
handleClick () { /*...*/ },

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`

相关链接:Prop Validation

使用特殊符号

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

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

相关链接:HTML Entities

Tables

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

// bad
render () {
  return (
    ...
); } // good render () { return ( ...
); }

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

classnames

使用classNames管理你的classes逻辑。

// bad
get classes () {
  let classes = ["MyComponent"];

  if (this.state.active) {
    classes.push("MyComponent--active");
  }

  return classes.join(" ");
}

render () {
  return 
; }
// good
render () {
  let classes = {
    "MyComponent": true,
    "MyComponent--active": this.state.active
  };

  return 
; }

相关链接:Class Name Manipulation

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80179.html

相关文章

  • 】TypeScript中的React高阶组件

    摘要:原文链接高阶组件在中是组件复用的一个强大工具。在本文中,高阶组件将会被分为两种基本模式,我们将其命名为和用附加的功能来包裹组件。这里我们使用泛型表示传递到的组件的。在这里,我们定义从返回的组件,并指定该组件将包括传入组件的和的。 原文链接:https://medium.com/@jrwebdev/... 高阶组件(HOCs)在React中是组件复用的一个强大工具。但是,经常有开发者在...

    wizChen 评论0 收藏0
  • React V16.9来了 无痛感升级 加入性能检测 【-真香】

    摘要:更新日志应对添加以编程方式收集性能测量。在和在将弃用为常见攻击面。添加对事件的支持。在从调用时发出警告,创建循环。在和从错误的渲染器使用时发出警告。 2019年8月8日,我们发布了React 16.9。它包含几个新功能,错误修正和新的弃用警告,以帮助准备未来的主要版本。 showImg(https://segmentfault.com/img/bVbwoB5?w=1728&h=666)...

    zzir 评论0 收藏0
  • React V16.9来了 无痛感升级 加入性能检测 【-真香】

    摘要:更新日志应对添加以编程方式收集性能测量。在和在将弃用为常见攻击面。添加对事件的支持。在从调用时发出警告,创建循环。在和从错误的渲染器使用时发出警告。 2019年8月8日,我们发布了React 16.9。它包含几个新功能,错误修正和新的弃用警告,以帮助准备未来的主要版本。 showImg(https://segmentfault.com/img/bVbwoB5?w=1728&h=666)...

    ky0ncheng 评论0 收藏0
  • 】展示型组件和容器型组件(作者:Dan Abramov,Redux的开发者)

    摘要:我的教程可能也会帮你一把其他的二分法展示型组件和容器型组件这种分类并非十分严格,这是按照它们的目的进行分类。在我看来,展示型组件往往是无状态的纯函数组件,容器型组件往往是有状态的纯类组件。不要把展示型组件和容器型组件的划分当成教条。 本文译自Presentational and Container Components,文章的作者是Dan Abramov,他同时也是Redux和Crea...

    lily_wang 评论0 收藏0
  • 正在失业中的《课多周刊》(第3期)

    摘要:正在失业中的课多周刊第期我们的微信公众号,更多精彩内容皆在微信公众号,欢迎关注。若有帮助,请把课多周刊推荐给你的朋友,你的支持是我们最大的动力。是一种祸害译本文浅谈了在中关于的不好之处。浅谈超时一运维的排查方式。 正在失业中的《课多周刊》(第3期) 我们的微信公众号:fed-talk,更多精彩内容皆在微信公众号,欢迎关注。 若有帮助,请把 课多周刊 推荐给你的朋友,你的支持是我们最大的...

    robin 评论0 收藏0

发表评论

0条评论

BicycleWarrior

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<