美文网首页
react.js 小书 学习笔记(二)

react.js 小书 学习笔记(二)

作者: koin447 | 来源:发表于2018-11-23 12:51 被阅读0次

    作者:胡子大哈
    原文链接: http://huziketang.com/books/react/lesson1

    看了 react.js 小书 第二阶段的内容,边看边做一点记录,整理了一些知识点。仅供学习。

    17.前端应用状态管理 —— 状态提升

    当某个状态被多个组件依赖或者影响的时候,就把该状态提升到这些组件的最近公共父组件中去管理,用 props 传递数据或者函数来管理这种依赖或者影响的行为。

    如何更好的管理这种被多个组件所依赖或影响的状态?

    你可以看到 React.js 并没有提供好的解决方案来管理这种组件之间的共享状态。在实际项目当中状态提升并不是一个好的解决方案,所以我们后续会引入Redux这样的状态管理工具来帮助我们来管理这种共享状态,但是在讲解到 Redux 之前,我们暂时采取状态提升的方式来进行管理。

    18.挂载阶段的组件生命周期(一)

    我们把 React.js 将组件渲染,并且构造 DOM 元素然后塞入页面的过程称为组件的挂载

    你可以理解一个组件的方法调用是这么一个过程:

    -> constructor()
    -> componentWillMount()
    -> render()
    // 然后构造 DOM 元素插入页面
    -> componentDidMount()
    // ...
    // 即将从页面中删除
    -> componentWillUnmount()
    // 从页面中删除
    

    componentWillMountcomponentDidMount都是可以像 render 方法一样自定义在组件的内部。挂载的时候,React.js 会在组件的 render 之前调用 componentWillMount,在 DOM 元素塞入页面以后调用 componentDidMount。

    总结:
    componentWillMount:组件挂载开始之前,也就是在组件调用 render 方法之前调用。
    componentDidMount:组件挂载完成以后,也就是 DOM 元素已经插入页面后调用。
    componentWillUnmount:组件对应的 DOM 元素从页面中删除之前调用。
    

    19.挂载阶段的组件生命周期(二)

    我们一般会把组件的 state 的初始化工作放在 constructor 里面去做;在 componentWillMount 进行组件的启动工作,例如 Ajax 数据拉取、定时器的启动;组件从页面上销毁的时候,有时候需要一些数据的清理,例如定时器的清理,就会放在 componentWillUnmount 里面去做。

    说一下本节没有提到的 componentDidMount 。一般来说,有些组件的启动工作是依赖 DOM 的,例如动画的启动,而 componentWillMount 的时候组件还没挂载完成,所以没法进行这些启动工作,这时候就可以把这些操作放在 componentDidMount 当中。componentDidMount 的具体使用我们会在接下来的章节当中结合 DOM 来讲。

    20.更新阶段的组件生命周期

    组件的挂载指的是将组件渲染并且构造 DOM 元素然后插入页面的过程。这是一个从无到有的过程

    除了挂载阶段,还有一种“更新阶段”。说白了就是 setState 导致 React.js 重新渲染组件并且把组件的变化应用到 DOM 元素上的过程,这是一个组件的变化过程

    关于更新阶段的组件生命周期:
    shouldComponentUpdate(nextProps, nextState):你可以通过这个方法控制组件是否重新渲染。如果返回 false 组件就不会重新渲染。这个生命周期在 React.js 性能优化上非常有用。

    componentWillReceiveProps(nextProps):组件从父组件接收到新的 props 之前调用。

    componentWillUpdate():组件开始重新渲染之前调用。

    componentDidUpdate():组件重新渲染并且把更改变更到真实的 DOM 以后调用。

    21.ref 和 React.js 中的 DOM 操作

    React.js 重新渲染的机制帮助我们免除了绝大部分的 DOM 更新操作,也让类似于 jQuery 这种以封装 DOM 操作为主的第三方的库从我们的开发工具链中删除。

    但是 React.js 并不能完全满足所有 DOM 操作需求,有些时候我们还是需要和 DOM 打交道。比如说你想进入页面以后自动 focus 到某个输入框,你需要调用 input.focus() 的 DOM API,比如说你想动态获取某个 DOM 元素的尺寸来做后续的动画,等等。

    React.js 当中提供了 ref 属性来帮助我们获取已经挂载的元素的 DOM 节点,你可以给某个 JSX 元素加上 ref属性。

    class AutoFocusInput extends Component {
      componentDidMount () {
        this.input.focus()
      }
    
      render () {
        return (
          <input ref={(input) => this.input = input} />
        )
      }
    }
    
    ReactDOM.render(
      <AutoFocusInput />,
      document.getElementById('root')
    )
    

    我们给 input 元素加了一个 ref 属性,这个属性值是一个函数。

    当 input 元素在页面上挂载完成以后,React.js 就会调用这个函数,并且把这个挂载以后的 DOM 节点传给这个函数。

    在函数中我们把这个 DOM 元素设置为组件实例的一个属性,这样以后我们就可以通过 this.input 获取到这个 DOM 元素。

    然后我们就可以在 componentDidMount 中使用这个 DOM 元素,并且调用 this.input.focus() 的 DOM API。整体就达到了页面加载完成就自动 focus 到输入框的功能。

    22.props.children 和容器类组件

    使用自定义组件的时候,可以在其中嵌套 JSX 结构。嵌套的结构在组件内部都可以通过props.children获取到,这种组件编写方式在编写容器类型的组件当中非常有用。而在实际的 React.js 项目当中,我们几乎每天都需要用这种方式来编写组件。

    23.dangerouslySetHTML 和 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 换成 fontSize,text-align 换成 textAlign。

    24.PropTypes 和组件参数验证

    都说 JavaScript 是一门灵活的语言,灵活性体现在弱类型、高阶函数等语言特性上。而语言的弱类型一般来说确实让我们写代码很爽,但是也很容易出 bug。

    大型应用程序的构建其实更适合用强类型的语言来构建,它有更多的规则,可以帮助我们在编写代码阶段、编译阶段规避掉很多问题,让我们的应用程序更加的安全。

    JavaScript 因为它的弱类型,常常意味着不是很安全。所以近年来出现了类似 TypeScript 和 Flow 等技术,来弥补 JavaScript 这方面的缺陷。

    React.js 就提供了一种机制,让你可以给组件的配置参数加上类型验证。

    我们这里先安装一个 React 提供的第三方库 prop-types:

    npm install --save prop-types
    

    导入import PropTypes from 'prop-types'

    static propTypes = {
      comment: PropTypes.object
    }
    

    我们可以通过 isRequired 关键字来强制组件某个参数必须传入:

    ...
    static propTypes = {
      comment: PropTypes.object.isRequired
    }
    ...
    

    React.js 提供的 PropTypes 提供了一系列的数据类型可以用来配置组件的参数:

    PropTypes.array
    PropTypes.bool
    PropTypes.func
    PropTypes.number
    PropTypes.object
    PropTypes.string
    PropTypes.node
    PropTypes.element
    ...
    

    25.实战分析:评论功能(四)

    持久化用户名

    用户输入用户名,然后我们把用户名保存到浏览器的 LocalStorage 当中,当页面加载的时候再从 LocalStorage 把之前保存的用户名显示到用户名输入框当中。

    ...
      componentWillMount () {
        this._loadUsername()
      }
    
      _loadUsername () {
        const username = localStorage.getItem('username')
        if (username) {
          this.setState({ username })
        }
      }
    
      _saveUsername (username) {
        localStorage.setItem('username', username)
      }
      
      handleUsernameBlur (event) {
        this._saveUsername(event.target.value)
      }
    ...
    

    监听用户名输入框失去焦点的事件,就存储用户名。

    组件挂载的时候把用户名加载出来。这是一种数据加载操作,不依赖 DOM 操作的组件启动的操作都可以放在 componentWillMount 中进行,加载用户名。

    组件的私有方法都用 _ 开头,所有事件监听的方法都用 handle 开头。把事件监听方法传给组件的时候,属性名用 on 开头。

    另外,组件的内容编写顺序如下:

    1. static 开头的类属性,如 defaultProps、propTypes。
    2. 构造函数,constructor。
    3. getter/setter。
    4. 组件生命周期。
    5. _ 开头的私有方法。
    6. 事件监听方法,handle*。
    7. render开头的方法,有时候 render() 方法里面的内容会分开到不同函数里面进行,这些函数都以 render 开头。
    8. render() 方法。

    26.实战分析:评论功能(五)

    持久化评论

    对象的存取要解析成JSON字符串

    _loadComments () {
      let comments = localStorage.getItem('comments')
      if (comments) {
        comments = JSON.parse(comments)
        this.setState({ comments })
      }
    }
    
    _saveComments (comments) {
      localStorage.setItem('comments', JSON.stringify(comments))
    }
    

    相关文章

      网友评论

          本文标题:react.js 小书 学习笔记(二)

          本文链接:https://www.haomeiwen.com/subject/unhjqqtx.html