平时写react 小技巧

  • Stateless function 无状态组件平时写组件用到比较多的就是无状态组件,不但优雅,也是优化react性能的一种手段。
    const Greeting = ({ name, style }) => { return <div style={style}>{name}</div> };
  • Array as children 把数组数据渲染出来

    常常会遇处处理数组数据的状况,能够用下面的方式简单的渲染出来。javascript

    render() {
          return ( (<ul> {List.map((item) => ( <li>{item}</li> ))} </ul>) ) }
  • 封装基础类组件

    好比 <input type="text" > 每次写很麻烦吧,能够封装一个成一个组件css

    const input = (props) => { return <input type = {props.type} {...props} /> }
  • Layout Component 布局组件

    组件能够分红不少类类,有的是布局类,有的是功能类。下面是一种布局类的组件。html

    <FlexContainer> <div style={{ flex: 1 }}>{this.props.leftSide}</div> <div style={{ flex: 2 }}>{this.props.rightSide}</div> </FlexContainer>
  • Higher Order Component 高阶组件

    高阶组件很像decorator,提高组件的能力。好比你想一些组件里面使用一下功能,react-router 中java

    import { withRouter } from 'react-router' withRouter(SomeComponent)

    例子:node

    var Enhance = ComposedComponent => class extends React.Component { componentDidMount() { this.setState({ name: "李狗子" }); } render() { return <ComposedComponent {...this.props} name = {this.state.name} />; } };
  • 受控组件,不受控组件

    项目中常常会用到这两种状况如:
    受控组件,更新的时候须要使用this.setStatereact

    constructor() { super(); this.state = {value: ""} } render() { return <input type="text" value={this.state.value} /> }

    不受控组件,主要须要经过ref来获取input的值。git

    render() { return <input type="text" ref="myInput" /> }

    两种方法均可以在特定的场合去使用,我的以为数据相对重要的页面须要使用受控组件会比较合适。github

  • 使用三元表达式

    项目中常常有判断语句,用三元表达式能够很方便的写出想要的逻辑npm

    const demo = ({ isOK }) => { return isOK ? <p> Yes </p> : <p> No </p> };
  • 给setState传入function

    可使用function来更新state数组

    this.setState((prevState, props) => ({ return ... }));
  • 经过ref属性获取component

    场景:下面的例子是初始化组件后,让input默认获取光标。ref最终指向的已经渲染好的DOM节点,或者是react class的实例。具体能够看官方的文档

    componentDidMount() {
          this.input.focus(); } render() { return ( <input ref={comp => { this.input = comp; }} /> ) }
  • 切勿使用...props传递数据

    一个很是错误的作法好比:

    <Component {...props} />

    props上面若是有很是多的属性,会形成很是昂贵的计算。正确的应该

    <Component name = { props.name } />

以上是平时写React用到的一些写法小技巧,说有用还蛮有用的!

有错误的地方还请指正!谢谢你们。

下面2个连接都很棒哦!记得收藏star...

参考:

https://github.com/vasanthk/react-bits

react 代码规范

https://github.com/airbnb/javascript/tree/master/react

 

 

dangerouslySetHTML 和 style 属性

 

dangerouslySetHTML

出于安全考虑的缘由(XSS 攻击),在 React.js 当中全部的表达式插入的内容都会被自动转义,就至关于 jQuery 里面的 text(…) 函数同样,任何的 HTML 格式都会被转义掉:

class Editor extends Component { constructor() { super() this.state = { content: '<h1>React.js 小书</h1>' } } render () { return ( <div className='editor-wrapper'> {this.state.content} </div> ) } } 

假设上面是一个富文本编辑器组件,富文本编辑器的内容是动态的 HTML 内容,用 this.state.content 来保存。我但愿在编辑器内部显示这个动态 HTML 结构,可是由于 React.js 的转义特性,页面上会显示:

表达式插入并不会把一个 <h1> 渲染到页面,而是把它的文本形式渲染了。那要怎么才能作到设置动态 HTML 结构的效果呢?React.js 提供了一个属性 dangerouslySetInnerHTML,可让咱们设置动态设置元素的 innerHTML:

...
  render () {
    return ( <div className='editor-wrapper' dangerouslySetInnerHTML={{__html: this.state.content}} /> ) } ... 

须要给 dangerouslySetInnerHTML 传入一个对象,这个对象的 __html 属性值就至关于元素的 innerHTML,这样咱们就能够动态渲染元素的 innerHTML 结构了。

有写朋友会以为很奇怪,为何要把一件这么简单的事情搞得这么复杂,名字又长,还要传入一个奇怪的对象。那是由于设置 innerHTML 可能会致使跨站脚本攻击(XSS),因此 React.js 团队认为把事情搞复杂能够防止(警示)你们滥用这个属性。这个属性没必要要的状况就不要使用。

style

React.js 中的元素的 style 属性的用法和 DOM 里面的 style 不大同样,普通的 HTML 中的:

<h1 style='font-size: 12px; color: red;'>React.js 小书</h1> 

在 React.js 中你须要把 CSS 属性变成一个对象再传给元素:

<h1 style={{fontSize: '12px', color: 'red'}}>React.js 小书</h1> 

style 接受一个对象,这个对象里面是这个元素的 CSS 属性键值对,原来 CSS 属性中带 - 的元素都必需要去掉 - 换成驼峰命名,如 font-size 换成 fontSizetext-align 换成 textAlign

用对象做为 style 方便咱们动态设置元素的样式。咱们能够用 props 或者 state中的数据生成样式对象再传给元素,而后用 setState 就能够修改样式,很是灵活:

<h1 style={{fontSize: '12px', color: this.state.color}}>React.js 小书</h1> 

只要简单地 setState({color: 'blue'}) 就能够修改元素的颜色成蓝色。

 

 

 

 

Prop 验证

随着应用不断变大,保证组件被正确使用变得很是有用。为此咱们引入propTypesReact.PropTypes 提供不少验证器 (validator) 来验证传入数据的有效性。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。注意为了性能考虑,只在开发环境验证 propTypes。下面用例子来讲明不一样验证器的区别:

React.createClass({ propTypes: { // 能够声明 prop 为指定的 JS 基本类型。默认 // 状况下,这些 prop 都是可传可不传的。 optionalArray: React.PropTypes.array, optionalBool: React.PropTypes.bool, optionalFunc: React.PropTypes.func, optionalNumber: React.PropTypes.number, optionalObject: React.PropTypes.object, optionalString: React.PropTypes.string, // 全部能够被渲染的对象:数字, // 字符串,DOM 元素或包含这些类型的数组。 optionalNode: React.PropTypes.node, // React 元素 optionalElement: React.PropTypes.element, // 用 JS 的 instanceof 操做符声明 prop 为类的实例。 optionalMessage: React.PropTypes.instanceOf(Message), // 用 enum 来限制 prop 只接受指定的值。 optionalEnum: React.PropTypes.oneOf(['News', 'Photos']), // 指定的多个对象类型中的一个 optionalUnion: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.number, React.PropTypes.instanceOf(Message) ]), // 指定类型组成的数组 optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), // 指定类型的属性构成的对象 optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), // 特定形状参数的对象 optionalObjectWithShape: React.PropTypes.shape({ color: React.PropTypes.string, fontSize: React.PropTypes.number }), // 之后任意类型加上 `isRequired` 来使 prop 不可空。 requiredFunc: React.PropTypes.func.isRequired, // 不可空的任意类型 requiredAny: React.PropTypes.any.isRequired, // 自定义验证器。若是验证失败须要返回一个 Error 对象。不要直接 // 使用 `console.warn` 或抛异常,由于这样 `oneOfType` 会失效。 customProp: function(props, propName, componentName) { if (!/matchme/.test(props[propName])) { return new Error('Validation failed!'); } } }, /* ... */ }); 
  static get propTypes () {     return {       todoLeft: PropTypes.number.isRequired,       actions: PropTypes.object.isRequired,       filter: PropTypes.string.isRequired     }   } ...   <strong>{this.props.todoLeft}</strong> ...

 

默认 Prop 值

React 支持以声明式的方式来定义 props 的默认值。

var ComponentWithDefaultProps = React.createClass({ getDefaultProps: function() { return { value: 'default value' }; } /* ... */ }); 

当父级没有传入 props 时,getDefaultProps() 能够保证 this.props.value 有默认值,注意 getDefaultProps 的结果会被 缓存。得益于此,你能够直接使用 props,而没必要写手动编写一些重复或无心义的代码。

传递 Props:小技巧

有一些经常使用的 React 组件只是对 HTML 作简单扩展。一般,你想少写点代码来把传入组件的 props 复制到对应的 HTML 元素上。这时 JSX 的 spread 语法会帮到你:

var CheckLink = React.createClass({ render: function() { // 这样会把 CheckList 全部的 props 复制到 <a> return <a {...this.props}>{'√ '}{this.props.children}</a>; } }); React.render( <CheckLink href="/checked.html"> Click here! </CheckLink>, document.getElementById('example') ); 

单个子级

React.PropTypes.element 能够限定只能有一个子级传入。

var MyComponent = React.createClass({ propTypes: { children: React.PropTypes.element.isRequired }, render: function() { return ( <div> {this.props.children} // 有且仅有一个元素,不然会抛异常。 </div> ); } }); 

Mixins

组件是 React 里复用代码最佳方式,可是有时一些复杂的组件间也须要共用一些功能。有时会被称为 跨切面关注点。React 使用 mixins 来解决这类问题。

一个通用的场景是:一个组件须要按期更新。用 setInterval() 作很容易,但当不须要它的时候取消定时器来节省内存是很是重要的。React 提供 生命周期方法 来告知组件建立或销毁的时间。下面来作一个简单的 mixin,使用 setInterval() 并保证在组件销毁时清理定时器。

var SetIntervalMixin = { componentWillMount: function() { this.intervals = []; }, setInterval: function() { this.intervals.push(setInterval.apply(null, arguments)); }, componentWillUnmount: function() { this.intervals.map(clearInterval); } }; var TickTock = React.createClass({ mixins: [SetIntervalMixin], // 引用 mixin getInitialState: function() { return {seconds: 0}; }, componentDidMount: function() { this.setInterval(this.tick, 1000); // 调用 mixin 的方法 }, tick: function() { this.setState({seconds: this.state.seconds + 1}); }, render: function() { return ( <p> React has been running for {this.state.seconds} seconds. </p> ); } }); React.render( <TickTock />, document.getElementById('example') );

关于 mixin 值得一提的优势是,若是一个组件使用了多个 mixin,而且有多个 mixin 定义了一样的生命周期方法(如:多个 mixin 都须要在组件销毁时作资源清理操做),全部这些生命周期方法都保证会被执行到。方法执行顺序是:首先按 mixin 引入顺序执行 mixin 里方法,最后执行组件内定义的方法。

 

 

 

 

 

这篇文章主要是写关于学习react中的一些本身的思考:

 

1.setState究竟是同步的仍是异步的?

2.如何在子组件中改变父组件的state

3.context的运用,避免“props传递地狱”

4.组件类里有私有变量a,它到底改放在this.a中仍是this.state对象中(做为属性a)呢?

 

1.setState究竟是同步的仍是异步的?

class MyComponent extends React.Component{ constructor(props) { super(props)  this.state ={ value:0 } } handleClick = () => {  this.setState({value:1}) console.log('在handleClick里输出' + this.state.value); } render(){ console.log('在render()里输出' + this.state.value); return (<div> <button onClick ={this.handleClick}>按钮</button> </div>)  } } export default MyComponent
//省略渲染过程,下面也同样

 

在这里咱们点击按钮时,调用handleClick函数,首先调用this.setState()设置value,随即把this.state.value输出,结果是什么?

你可能会想,这还不简单——“在handleClick里输出1”呗,然而你错了,它的结果为:

 

事实上,setState()的调用是异步的,这意味着,虽然你调用了setState({value:0}),但this.state.value并不会立刻变成0,而是直到render()函数调用时,setState()才真正被执行。结合图说明一下:

 

你可能又会问了:要是我在render()前屡次调用this.setState()改变同一个值呢?(好比value)

 

咱们对handleClick作一些修改,让它变得复杂一点,在调用handleClick的时候,依次调用handleStateChange1 ,handleStateChange2,handleStateChange3,它们会调用setState分别设置value为1,2,3而且随即打印

handleStateChange1 = () => {  this.setState({value:1}) console.log('在handleClick里输出' + this.state.value); } handleStateChange2 = () => {  this.setState({value:2}) console.log('在handleClick里输出' + this.state.value); } handleStateChange3 = () => {  this.setState({value:3}) console.log('在handleClick里输出' + this.state.value); } handleClick = () => {  this.handleStateChange1();  this.handleStateChange2();  this.handleStateChange3(); }

 

那么输出结果会是什么呢?若是setState是同步调用的,那么结果显然为

在handleClick里输出1

在handleClick里输出2

在handleClick里输出3

 

可是结果为:,证实它是异步的

 

这下好理解了吧,配合这幅图:

2.如何在子组件中改变父组件的state呢?

这是咱们常常会遇到的问题之一,解决办法是:在父组件中写一个能改变父组件state的方法,并经过props传入子组件中

class Son extends React.Component{ render(){  return(<div onClick = {this.props.handleClick}> {this.props.value}  </div>)  } } class Father extends React.Component{ constructor(props){ super(props)  this.state ={ value:'a' } } handleClick = () => {  this.setState({value:'b'}) } render(){  return (<div style ={{margin:50}}> <Son value = {this.state.value} handleClick = {this.handleClick}/> </div>)  } }

 

点击子组件Son,内容由a变成b,说明父组件的state被修改了

3.context的运用,避免“props传递地狱”

 

3.1假设一个比较极端的场景:你须要从你的子组件里调用父父父父父组件的属性或方法,怎么办!当组件嵌套层级过深的时候,不断地传props做为实现方式简直就是噩梦!我称之为“props传递地狱”(这个词是我瞎编的,参考自“回调函数地狱”)

 

咱们接下来实现的是这样一个需求,把gene属性(基因)从组件GrandFather -->Father --> Son传递,若是用props传递:

class Son extends React.Component{ render(){  return (<h3 style ={{marginTop:30}}>我从个人爷爷那里获得了基因--{this.props.gene}</h3>)  } } class Father extends React.Component{ render(){  return (<Son gene = {this.props.gene}/>)  } } class GrandFather extends React.Component{ constructor(props) { super(props)  this.state ={ gene:'[爷爷的基因]' } } render(){  return (<Father gene = {this.state.gene}/>)  } }

demo:

 

【(。・`ω´・)虽然听起来有点怪怪的可是你们别介意哈】

 

实现是实现了,但你想一想,假设不是从“爷爷”组件,而是从“太太太太爷爷”组件传下来,这多可怕!不过不要紧,react提供了一个叫作context(上下文)的API,你在顶层组件的context中定义的属性,能够在全部的后代组件中,经过this.context.属性去引用!让咱们一睹为快:

class Son extends React.Component{ render(){ console.log(this.context.color);  return (<h3 style ={{marginTop:30}}>我从个人爷爷那里获得了基因--{this.context.gene}</h3>)  } } Son.contextTypes ={ gene:React.PropTypes.string } class Father extends React.Component{ render(){  return (<Son/>)  } } class GrandFather extends React.Component{ getChildContext(){  return {gene:'[爷爷的基因]'} } render(){  return (<Father />)  } } GrandFather.childContextTypes = { gene: React.PropTypes.string }; export default GrandFather

demo效果同上!这个时候你发现,咱们在<GrandFather>组件和<Father>组件中都没有向下传递props,咱们就从最下层的Son组件中获取了gene属性,是否是很方便!

 

解释下代码:

getChildContext()是你在顶层组件中定义的钩子函数,这个函数返回一个对象——你但愿在后代组件中取用的属性就放在这个对象中,譬如这个例子中我但愿在Son组件中经过this.context.gene取属性,因此在getChildContext()中返回{gene:'[爷爷的基因]'}

GrandFather.childContextTypes和Son.contextTypes 用于规定顶层组件和取顶层组件context的后代组件的属性类型

 

【注意】GrandFather.childContextTypes和Son.contextTypes 这两个对象必需要规定!不然context只能取到空对象!一开始我犯的这个错误简直让我狂吐三升血。。。。

 

有图有真相之context和props的区别

 

3.2context是否推荐使用?

虽然上面这个例子说明了context多么好用,但注意:官方并不推荐常用它,由于它会让你的应用架构变得不稳定(官方文档原话If you want your application to be stable, don't use context),在我看来,为何在大多数状况下要使用props而不是实现数据流呢,由于props凭借组件和组件间严密的逻辑联系,使得你可以清晰地跟踪应用的数据流(it's easy to track the flow of data through your React components with props)固然了,若是你遇到上述的例子的状况,context仍是大有裨益的 

3.3须要改变context中的属性时候,不要直接改变它,而是使用this.state做为媒介,若是你试图在顶层组件的state中放入一个可变的属性你能够这样作:

getChildContext(){ return {type:this.state.type} }

 

3.4在上述我限制gene的类型时候我是这样写的:gene: React.PropTypes.string,使用了React内置的React.PropTypes帮助属性,此时个人版本为 "react": "15.4.2",在15.5的版本后这一帮助属性被废弃,推荐使用props-types库,像这样:

const PropTypes = require("Prop-Types"); GrandFather.childContextTypes = { gene: PropTypes.string };

 

固然,在这以前你须要npm install prop-types

 

4组件类里有私有变量a,它到底改放在this.a中仍是this.state对象中(做为属性a)呢?

这得根据它是否须要实时的重渲染决定,若是该变量须要同步到变化的UI中,你应该把它放在this.state对象中,若是不须要的话,则把它放在this中(无代码无demo)

相关文章
相关标签/搜索