react 笔记

  1. react 基本概念解析
  2. react 的组件声明周期
  3. react 高阶组件,context, redux 等高级进阶

特别提醒:

  1. 新版本更新
    React.createClass({ ..... }) 为es5 的写法,新版已经被废弃
    class { ..... } 为 es6 的写法,推荐使用

  2. create-react-app 工程为自动创建新 react 工程的工具项目,该工具包含了打包、 测试、sourceMap、等功能。

  3. react 使用全家桶( react 项目中不可或缺的工具 )
    React 在开发/生产 阶段需要一大堆的工具库辅助开发
    编译:babel
    状态管理工具:redux
    单页应用:react-route

  4. dangerouslySetInnerHTML 用于设置不受保护的HTML

  5. 好的 React 命名习惯

    • 自定义的组件使用 首字母大写的驼峰命名 (eg: InputComponent..... )
    • 自定义的属性使用 小驼峰命名 ( eg: this.state.getDate..... )
    • 事件尽可能以 handle... 开头命名 (eg: handleChange....)
    • 组件私有的自定方法以下划线 _..... 开头命名 (eg: _getLocalDate...... )
  6. react 概念大全
    事件系统 + 表单应用 + 样式处理 + 组件通讯 + 组件抽象 + 组件性能优化 + 动画 + 自动化测试

一:react 基本概念解析

  1. react 描述 DOM 的 方式 (JSX)jsx 其实就是 JavaScript 对象
  • 在 javascript 中使用类似于 HTML 结构和信息的语法为 JSX 语法。

    很容易转换编译成为 于 HTML 信息的 JavaScript 表示形式( `HTML 的 对象形式` )。
    
    可以根据平台 编译成为 第三方页面 UI 结构
    
react 笔记_第1张图片
jsx编译过程.png
  • ReactDOM 解析
    ReactDOM 是 react 提供的 WEB 页面构建对, 在 移动端 该对象是 ReactApp
    ReactDom 有三个方法:
    findDomNode( this ) // 用于获取页面中的DOM 元素
    UnmountComponentAtNode()
    render() // 用于页面渲染

  • ref 和 findDomNode 获取页面元素辨析
    ref 添加到 Component 上获取的是 Component 实例,
    ref 添加在 原生的 HTML 上获取的是 DOM 节点

        findDomNode 当参数是 DOM 时 就返回一个 DOM( 貌似没什么用 )
        findDomNode 当参数是 Component 时返回 Component 中的 render 中的 DOM
        
        
    { this._div = div }}>app
    this._child = child}/>

    特点
    1. react 使用 jsx 描述 DOM / UI 结构
    2. jsx 预防在编译阶段 会转换为 DOM 的 JavaScript 表现形式
    3. ReactDom 对象只有一个作用 ---> 负责将 JavaScript 对象 渲染成为 真正的页面 DOM
    4. 在渲染过程中 react-dom( web ) ,react-canvas( canvas ) ,react-app (react-native) 可分别将该 JS 对象渲染到不同的平台上

  1. render 函数中都可以写什么

render 函数能且只能 返回一个 jsx 对象, 就是必须 返回一个值,并且这个值 是一个 类似于 DOM 的 jsx 语法

  • jsx 结构中可以使用 { } ( 大括号 ) 插入 表达式

    { } 大括号中 可以放置任何表达式内容( 包括 函数,jsx 结构,变量,对象,表达计算式 )

      ...
      render () {
          const isGoodWord = true
          return (
                      
    React 小书 { // jsx 中的注释 只能写在 大括号中 // 下面表示一个三目表达式 // 这里不能写 JavaScript 的 多行表达式 isGoodWord ? is good : is not good } { // 下面表示一个自执行函数,函数中可以做任何你想做的事,也可以有多行代码 (function() { .... doSomething }) }
    ) } ...
  • jsx 结构中的 null 表示什么都不显示,相当于忽略了该表达式的插入,可以使用这个特性来 隐藏元素

  • jsx 结构整体当做变量用于 参数传递或者使用

    jsx 语法其实就是一个个 js 的对象,所以可以使用任何变量能使用的方式传递或者使用它们

     ...
      render () {
          const isGoodWord = true
          const goodWord =  is good    // 这是一个 jsx 变量
          const badWord =  is not good   // jsx 变量还可以当做 函数参数传递
          return (
              
    React 小书 {isGoodWord ? goodWord : badWord}
    ) } ...
  • 在 render 的 {} 中 可以使用 map 等 返回 DOM LIST 的函数方法

      // 必须返回一个 表示 DOM LIST 
     const arr = [1, 2, 3, 4, 5];
     render () {
          return (
                
            )
      }
      ...
    
  • jsx 中的 三元表达式 其实就是一句完整的表达式,所以可以被 识别

  1. jsx 语法中 注释的写法

    注释只能写在 JavaScript 表达体 中( 即只能 写在 { } 大括号中 ),写在 大括号外面的注释不被识别
    要是真的想写注释,可以给某个或者某条语句外面添加一个 大括号,然后在进行注释

  2. 组件嵌套

组件和组件之间可以 嵌套使用。但是所有的自定义组件都必须是以 大写字母开头的组件。

  1. 事件系统

    • 每个 jsx 元素上面都可以自己定义 on* 类型的事件监听函数,只能用在普通的 html 元素标签上,不能使用在自定义的元素标签上

    • 每个事件监听函数 都有一个默认的 event 对象。一个经过 react 包装的 event 对象

    • react 的事件代理机制
      react 将事件处理函数统一绑定在最外层上面
      react 对于原生的 DOM 节点可以书写原生的事件
      ** 特别注意 **: 因为 react 的事件代理机制,注意 stopPropagation() 阻止事件冒泡的时机

    • 注意 每个 事件监听函数 若内部有使用到 this 的情况,需要在声明函数的地方,动态的绑定 this

      // bind this 的时候 可以 传递默认的 参数
      render () {
          return (
              

      React 小书

      ) }
    • react 的 this 自动绑定区域
      A. class 内部自动绑定 this ( class 的 { } 大括号这一层级 自动绑定 this )
      B. 构造函数 constructor 中没有自动绑定this
      C. 箭头函数自动绑定this
      D. 使用 bind 显示绑定 this

  2. state 的 使用

    • 每次调用 setState 都会触发 react 的重新渲染,并且重新调用 render 方法 **
  • setState 函数执行时可以接受一个参数(prevState)
  • 多个 setState 执行需要合并时 需要 prevState 参数的帮忙。并且 react 会将 多个 setState 操作合并为一个最终的状态进行一次性渲染
  • react 自己的 diff 算法保证只会渲染更改的地方
  1. props 的使用
  • props 带来更好的复用性和 可配置性

  • defaultProps设置组件默认的 props, 和 this.props 获取配置参数,设定 组件的默认 props 数据

  • 组件内部一旦传递进 props 不可以在组件内部更改 props
    但是 组件内部 可以获取 props. 将其赋予 state 或者 其他变量进行数据的增删改。

组件的生命周期


  1. 前端的状态数据管理, - 状态提升

将组件之间共享的数据抽象并提取出来放到最近的 公共父节点上,然后通过 props 将数据传递给子组件, 这样就是一个状态数据的提升。

那么问题来了? 怎样管理 多个层次的组件 所依赖的状态呢 ?
( ** 请大家关注 context 和 redux 的相关内容 ** )

  1. 组件的基础生命周期
react 笔记_第2张图片
组件声明周期过程.png

react 将组件渲染 并塞到 DOM 元素中然后绘画在页面上的过程称为组件的挂载

所以 由挂载的过程你可以很好的理解下面的组件处理过程

constructor() // 初始化状态数据
componentWillMount() // 组件的挂载过程
render()
// 构造 DOM 元素 插入页面
componentDidMount() // 组件的挂载过程
。。。。。
// 即将从页面中删除元素
componentWillUnmount()
// 从页面中删除元素

以上 的几个生命周期 都是 组件的 第一阶段的状态管理函数

  • 一般的 getDefaultProps 和 getInitialState 都会放在 constructor 中完成
  • 组件的隐藏 会触发 页面的 componentWillUnmount() 函数,所以,在页面被隐藏时要注意剩余数据 的处理。
  • componentWillMount() 函数多用于组件的启动,eg: ajax, localStore数据的拉取,定时器的启动,等工作。
  • componentDidMount() 函数用于依赖 DOM 的事件动作或者其他。eg: 动画的启动需要依赖 DOM. componentWillMount 的时候 DOM 还没有挂载完成,所以动画的启动需要放在 DidMount 函数中完成
  1. 组件更新的生命周期

    shouldComponentUpdate(nextProps, nextState) 返回一个 boolean 数据。 用于控制组件是否 重新渲染。
    componentWillReceiveProps(nextProps). 多用于处理父组件传递过来的 props
    componentWillUpdate(); 组件开始更新之前调用。
    componentDidUpdate(); 组件更新并且重新渲染到 DOM 之后调用。

  2. ref 的作用

ref 属性用于获取已经挂载的 DOM 节点( 类似于为元素添加 id 属性,用于表示元素 )
refs 用于引用已经 标识的 DOM 节点,获取其 对象的 属性 和 方法

** 注意: ** 多余 的 DOM 操作 会产生代码的噪音,不推荐大量使用 ref 操作 DOM

ref 版本改动:标识 DOM 节点的 ref由原来的字符串改为一个回调函数
旧版本
新版本 {this.myinput=input;}}/> 可以额外有一个参数 参数有妙用

  1. props.children 和 自定义标签元素中 添加 额外的 HTML DOM 元素

普通的标签元素中内嵌的 DOM 元素可以直接添加。但是自定义标签组件怎讲将内嵌的 DOM 内容传递到下一层呢?

我们使用 props.children 可以获取到上层的 自定义标签中的内嵌的 DOM 元素

  1. jsx 中任何的 html 格式的 代码都会被转义掉,为了防止 xss 攻击

    为了显示 带有 html 标签的元素我们需要用到元素的 dangerouslySetInnerHTML (
    这个只是元素的一个属性

    .....
    render() {
          renturn (
             
    ) } .....
  2. propsTypes 和 组件的参数验证
    JavaScript 是弱类型的语言,但是为了 ** 防止和校验上一层传递过来数据的正确性,我们使用 PropTypes 来做数据类型的校验相当于为数据添加数据类型,强类型的数据 **

     import React, { Component, PropTypes } from 'react'
     ....
     class ChildComponent extends Component {
           // 下面这些是固定的 书写格式
           static propsTypes = {
                 parentAttr: PropTypes. object,
                 parentArr: PropTypes.array
           }
           .........
     }
     ......
    
  3. 高阶组件就是一个函数,你传递给他一个组件对象,他返回给你一个经过包装的组件对象
    ** 相当于在原始组件之上 添加了一层经过封装的父组件 ** 功能性的封装

    ** 作用:**

    • 组件状态提升
      将子组件需要操作的数据交给父组件来管理,然后通过 props 向下传递数据。此为 状态提升
      当某个数据/状态 被多个组件依赖/使用 时,应该通过状态提升来管理

    • 高阶组件本质就是为了组件之间的复用,将重复的代码 操作放在高阶组件中,下面的基本组件就可以复用了

       比如数据的 ajax 的读取,事件的统一操作等
      
    • 高阶组件中 通过 props 传递数据

    • 高阶组件可以很好的实现 Smart 组件( 依赖数据操作的组件/ 高阶组件 ) 和 Dumb 组件( 只需要上层数据props的纯组件 ) 的分离

      Smart 组件和 Dumb 组件( 或者说高阶组件 )的出现,很好的实现了 react 的 mvc 结构,达到了高层次的 组件的复用。

高阶组件知识点
1. 高阶组件 本质就是一种 组件的 mixin 模式
1. es7 的装饰着模式可以用来扩展高阶组件
2. 一个 Smart 组件可以被多个高阶组件装饰,并且按照顺序执行

react 笔记_第3张图片
高阶组件.png
  1. react 的 context 作为全局的对象,有自己独特的写法

    ** context 必须和 propType 强制数据类型 共同使用 **

    • 强制数据类型
      import React, { Component, PropTypes } from 'react'
      ......
      static propsTypes = {
      themeColor: PropTypes. string
      }

    • 定义context 时的写法

      import React, { Component, PropTypes } from 'react'
      ....
      class ParentComponent extends Component {
          // 下面这些是固定的 书写格式
          static propsTypes = {
                themeColor: PropTypes. string
          }
          .........
          // 这里设置了 本组件包括其 所有子组件的 context 
          getChildContext () {
                 return { themeColor: this.state.themeColor }
          }
      }
      ......
      

    context 在定义时,必须有两个步骤
    声明属性的数据类型
    设置获取全局 Context 的方法 getChildContext

    • 使用 context

            import React, { Component, PropTypes } from 'react'
            ....
            class ChildComponent extends Component {
                  static propsTypes = {
                        themeColor: PropTypes. string
                   }
                  render () {
                          return (
                                
      context 的获取使用地方
      ) } }

    context 在使用时必须有两个步骤
    声明要使用的 context 数据类型
    使用 this.context.属性 获取属性的值

context 使用步骤繁杂是有原因的
1. context 作为全局拥有的对象,必须保证其数据的正确性。
2. react 官方不推荐使用 context, 进而希望大家能够使用更为友好的 Redux, Mobx等

React 组件进阶


  1. react 理念分析

    • React 的组件本质是创建了一个对象,由框架本身添加了 10 个声明周期函数( 其实就是普通的函数,只是有执行顺序、触发时机、优化处理等特点 )
      具体参见 React 的最初写法 React.createClass({ .... }), 中间是一个对象

    • 声明周期函数,就是对象中的普通函数
      传值 + 操作处理 + 返回值

    • react 特点:
      1. 简洁: 足够的简洁,其本身只有自己的 api
      2. 非声明式的单项数据绑定
      3. ** 面向 HTML5, 专注视图层操作 ** 将 JavaScript 和 HTML5 整合在一起。
      4. 高性能的密集 DOM 操作
      5. 支持后端渲染。
      6. 跨平台,一种书写,能够编译出多种结果 ** ReactNative **

      react 函数式编程 ( 小函数编程 )
      1. 尽可能抽象出公共使用的小函数。
      2. 在一个庞杂的 逻辑体 中能够提取出 功能小函数

    • 组件化
      狭义的组件化:ui组件 ---> 具体的组件( Tabs 组件 / Dropdown 组件 )
      广义的组件化: 业务数据 + UI 组件的组合使用

      组件化的发展进程

      DOM操作为主( 根据逻辑改变 DOM 结构 ) --> MVC( 数据和界面解耦 ) --> 小组件( 数据 + 界面 + 样式的结合体 eg: angular 指令 ) ----> HTML5 的引入 ( javascript + HTML + css 合为一体)

      HTML Templetes --> custom Element --> shadow DOM --> HTML Imports

    • ** 非常重要:**
      ** 组件封装的进程其实就是面向对象的思想逐步成熟** (通过实例化的方法制造对象

      一个组件的对象实例: ( 基本的封装性 + 简单的声明周期 + 明确的数据流动 )

  2. 表单组件

    表单组件分为受控组件和非受控组件
    受控组件:依靠 state 和内部事件 改变状态的组件,有很强的耦合性,复用性不高

       非受控组件,通过 defaultProps, props 传值的组件,复用性好
               非受控组件可以通过 事件和 ref 向上传递数据
    
  3. 组件通讯 ---> 事件订阅
    EventEmitter

  4. 组件性能优化

    1. 引入纯函数( pureRender 函数或者 Smart组件 )

    2. 使用 数据对比决定 纯函数组件是否渲染 shouldComponentUpdate()

    3. 引入不可变对象 或者 es6 对象扩展 进行数据对比

         Immutable 不可变对象,对 Immutable 对象的 增 删 改 都会生成一个新对象,类似于对象的深拷贝,但是比对象的深拷贝效率要高
      
         es6 对象扩展 和 对象/数组的解构赋值,也能够得到一个新的对象
      
    4. Immutable 解析

      ** Immutable 可以提供一种全新的数据对比和生成形式,类似于 es6 的对象扩展 和 解构赋值 **

         Immutable 三种数据类型 
         Map: 对应于 `Object`, 键值对集合
         List :   对应于 `Array` 有序的重复列表
         ArrayList: 无序不可重复的列表
      
         // 特性应用实例
         import { Map, List, Arraylist } from 'immutable'
         ....
         this.setSatate({
                 data: Map({ times: 0 })      // 得到一个新的 Immutable 对象
         })
      

      Immutable 方法应用实例 ( Immutable.is 可以用来进行比较,比 === 全等的效率高 )

         import { is } from 'immutable'
         .....
         shouldComponentUpdate(nextProps, nextState) {
               if( is( nextProps.attr, nextState.attr ) )
                     return false;
              ......
         }
      

.

你可能感兴趣的:(react 笔记)