React——第二阶段

根据胡子大哈的文章学习,感谢大胡分享
胡子大哈-第二阶段

一、理解状态管理

状态管理是为了解决一个问题:

如何高效的管理被多个组件依赖或影响的状态?

state和props都是状态池,里边的字段就是状态。
当父组件中有多个子组件需要某个状态,那么这个时候,这个状态要保存在父组件来达到共享。
但是,如果父组件只是爷爷组件的其中一个孩子,而其他的父组件的兄弟组件也需要这个状态。那么这个状态就要保存在爷爷组件。
如上循环,这种将某个状态往外层放的情况,叫做状态提升。
在实际项目中,可能遇到,嵌套较深的两个组件依赖同一个状态的情况,这个时候如果使用状态提升的方法,就需要把这个状态提升到很外层的组件里,显然不是一个好方法

Redux就是解决这个问题的,关于它,将在下一阶段复习

一般的不被多个组件依赖的状态,内部保存就行。

二、生命周期

1.组件挂载
过程:
实例化组件(constructor())-->调用render生成元素对象(react.js)-->将元素对象构建成dom对象(reactDOM)-->插入页面

以上就是挂载。
抽象一下,就是这个过程

-> constructor()
-> render()
-> 构造dom
-> 插入页面

2.挂载生命周期与控制钩子

  • 为了更好的控制挂载过程

React.js提供了两个钩子
componentWillMount()componentDidMount()
两个方法在组件内部定义,
在组件的render之前调用componentWillMount()
在DOM元素插入页面后调用componentDidMount()
抽象下

-> constructor()
   -> componentWillMount()
-> render()
-> 构造dom
-> 插入页面
   -> componentDidMount()
  • 完善过程——删除页面钩子

完善上边抽象的过程

-> constructor()
   -> componentWillMount()
-> render()
-> 构造dom
-> 插入页面
   -> componentDidMount()
...
-> 将从页面中删除
-> 已从页面中删除

React.js同样控制了这个过程,componentWillUnmount()

-> constructor()
   -> componentWillMount()
-> render()
-> 构造dom
-> 插入页面
   -> componentDidMount()
...
-> 将从页面中删除
 -> componentWillUnmount()
-> 已从页面中删除

注:
删除一个组件是很经常的,一个标签的隐藏和显示{this.state.isShow ? <App /> : null}类似这样的逻辑。

  • 挂载过程的一些说明
    constructor:初始化工作,比如state
    componentWillMount:一些组件启动时的行为,比如Ajax、定时器
    componentWillUnmount:清场工作,比如取消定时器,防止各种错误,比如内存泄漏。

3.更新阶段组件生命周期

  • 更新过程:
    setState --> render --> dom --> 插入页面
    要理解这个过程,就需要对virtual--DOM有比较深刻的认识,这些将在第四阶段复习。
    接下来,大概了解下更新过程和这个过程中的钩子

  • 钩子函数
    shouldComponentUpdata(nextProps, nextState):通过这个方法,控制组件是否重新渲染。
    componentWillReceiveProps(nextProps):组件从父组件接收新的props之前调用
    componentWillUpdate():组件开始重新渲染之前调用
    componentDidUpdate():组件重新渲染并且把更改变更到真实的DOM以后调用

4.小总结
这里引用一些网上文章的内容
下文引用自NsNe的博客

每个组件都有几个生命周期函数,以will为前缀的函数是在发生某些事之前调用,以did为前缀的是在发生某些事之后调用

1.Mounting
如下这些方法在组件实例被创建和被插入到dom中时被调用。

  • constructor()

  • componentWillMount()
      此方法在mounting之前被立即调用,它在render()之前调用,因此在此方法中setState不会触发重新渲染。此方法是服务器渲染中调用的唯一的生命周期钩子,通常我们建议使用constructor()。

  • render()

  • componentDidMount()
      此方法在组件被mounted之后立即被调用,初始化dom节点应该在此方法中,如果需要从远端健在数据,这里是实例化网络请求的好地方,此方法中setState会触发组件重新渲染。

Updating
props和state的改变产生更新。在重新渲染组建时,如下的方法被调用

  • componentWillReceiveProps()
      一个已经mounted的组件接收一个新的props之前componentWillReceiveProps()被调用,如果我们需要更新state来响应prop的更改,我们可以在此方法中比较this.props和nextProps并使用this.setState来更改state。
      注意,即使props没有改变,React也可以调用这个方法,因此如果你只想处理改变,请确保比较当前值和下一个值。当父组件导致你的组件重新渲染时,可能会发生这种情况。
      React在组件mounting期间不会调用此方法,只有在一些组件的props可能被更新的时候才会调用。调用this.setState通常不会触发componentWillReceiveProps。
  • shouldComponentUpdate()
      使用此方法让React知道组件的输出是否不受当前state或props更改的影响。默认行为是在每次state更改时重新渲染组件,在大多数情况下,我们应该默认改行为。
      当接收到新的props或state时,shouldComponentUpdate()在渲染之前被调用。默认返回true,对于初始渲染或使用forceUpdate()时,不调用此方法。返回false不会阻止子组件的state更改时,该子组件重新渲染。
      如果shouldComponentUpdate()返回false,那么componentWillUpdate(),render()和componentDidUpdate()将不会被调用。在将来,React可能将shouldComponentUpdate()作为提示而不是strict指令,返回仍然可能导致组件重新渲染。
  • componentWillUpdate()
      当接收新的props或state时,componentWillUpdate()在组件渲染之前被立即调用。使用此函数作为在更新发生之前执行准备的机会。初始渲染不会调用此方法。注意:这里不能调用this.setState()(如果调用会怎么样?好奇心很重呀,试了一下,会产生死循环,一直更新。。。)。如果我们需要更新state以响应props的更改,我们应该使用componentWillReceiveProps()
  • render()
  • componentDidUpdate()
      此函数在更新后立即被调用。初始渲染不调用此方法。
      当组件已经更新时,使用此操作作为DOM操作的机会。这也是一个好的地方做网络请求,只要你比较当前的props和以前的props(例如:如果props没有改变,可能不需要网络请求)。

Unmounting
当从dom中移除组件时,这个方法会被调用

  • componentWillUnmount()
      此函数在组件被卸载和销毁之前被立即调用。在此方法中执行一些必要的清理。例如清除计时器,取消网络请求或者清理在componentDidMount中创建的任何DOM元素。

三、ref

流行的前端大框架,基本上都避免了绝大部分的DOM更新操作,jQ基本88。

但是,框架提供的功能并不能满足所有的需求。所以,有时候还是要和DOM打交道。

比如动态获取某个元素尺寸,然后做动画。

React.js的ref属性
通过这个属性,可以获取已经挂载的元素对应的真实DOM节点。
用法:

<Index ref={(Index) => this.index = Index} />

当然,一般是标签,不是组件,这里只是示例。

布局

一般情况下,在写页面的时候,会有很多容器标签,来给页面布局。组件化开发,同理,就会有一些容器组件,用来布局。

如何方便的使用这些组件?既然是容器组件,那么调用组件的时候,是不是要传入容器里的内容,然后让容器渲染呢?

通过porps,在字段中书写JSX显然是不方便的。React.js提供了props.children属性,它是一个数组,保存了调用组件时,组件闭合标签内的结构。
在组件内部,就可以直接使用这个属性了。

class Layout extends Component {
  render () {
    return (
      <div className='two-cols-layout'>
        <div className='sidebar'>
          {this.props.children[0]}
        </div>
        <div className='main'>
          {this.props.children[1]}
        </div>
      </div>
    )
  }
}

...// 调用的时候
某个组件调用Layout组件
render () {
  return (
    <Layout>
      <div>你们好</div>
      <div>哈哈哈</div>
    </Layout>
  )
}

五、dangerouslySetInnerHTML

为避免xss,React.js将所有通过表达式插入的内容自动转义——>字符串

如何向其中插入HTML结构(innerHTML)?

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

// this.state.content: <div>一个标签</div>

六、style

在标签中,style字段接收一个对象,而不是原生的字符串。
在对象中,对应css字段命,使用小驼峰命名。eg:background-color——>backgroundColor

因为style是一个对象,我们就可以使用状态池中的状态了,很方便。

七、数据验证

1.理解验证的重要性
多人协作,组件复用,没有验证,健壮性就太差。

2.React.js的验证机制

  • 引入prop-types
  • 定义propTypes字段,对输入进行检查
  • propTypes提供的参数
PropTypes.array
PropTypes.bool
PropTypes.func
PropTypes.number
PropTypes.object
PropTypes.string
PropTypes.node
PropTypes.element
等等

更多点此查看官网

多人协作开发,写类型检查吧,省事好维护

(完)

推荐阅读更多精彩内容

  • React 元素 ReactNode ReactNode 是虚拟 DOM 的基本构建,可以是以下任意一种核心类型 ...
    不二很纯洁阅读 6,616评论 3 77
  • 本笔记基于React官方文档,当前React版本号为15.4.0。 1. 安装 1.1 尝试 开始之前可以先去co...
    Awey阅读 6,771评论 14 129
  • It's a common pattern in React to wrap a component in an ...
    jplyue阅读 2,641评论 0 2
  • “你刚才说穿垮裤啊?对呀,我生活中穿的很舒服就好了,对。然后就是他们好像会说,如果说是演员或者做演艺的,好像衣服不...
    戴梦阅读 29评论 0 0
  • ——❤—— 你是否 还记得 当初见我的第一眼 ——❤——
    七柒v阅读 506评论 0 1