React笔记1

一、准备知识

ES6、JSX

二. 组件

定义组件的两种方式:使用ES 3 class(类组件)和使用函数(函数组件)

  • 使用class定义组件:

    • class 继承自React.component
    • class内部必须定义render方法,render方法返回代表该组件UI的元素;
  • 使用函数定义组件:

    • 函数组件接收props作为参数,返回代表这个组件UI的React元素结构;
    • 函数组件的写法比类组件的写法简洁,在使用无状态组件时,应该尽量将其定义为函数组件。

1.state、props

  • React组件可以看作是一个函数,函数的输入是props和state,函数的输出是组件的UI;
  • React组件正是由props和state两种类型的数据驱动渲染出组件UI;
  • props是组件对外的接口,组件通过props接收外部传入的数据(包括方法);
  • state是组件对内的接口,组件内部状态的变化通过state反映;
  • props是只读的,不能再组件内部修改props;
  • state是可变的,组件状态的变化通过修改state来实现。

2. 有状态组件、无状态组件

  • 如果组件内部状态是不变的,即用不到state,这样的组件称为无状态组件;
  • 如果组件内部状态是可变的,需要使用state来保存变化,这样的组件称为有状态组件;
  • 无状态组件不用关心状态变化,只聚焦UI的展示,更容易复用,应该尽可能多地使用无状态组件;
  • React应用组件设计的一般思路是:通过定义少数的有状态组件管理整个应用的状态变化,并且将状态通过props传递给其余的无状态组件,由无状态组件完成页面绝大部分UI的渲染工作。即,有状态组件主要关注处理状态变化的业务逻辑,无状态组件主要关注组件UI的渲染。

3.属性校验和默认属性

  • 属性校验

    • react 提供PorpType这个对象,用于校验组件的类型;
    • 通过定义一个对象(对象的key是组件的属性名,value是对应属性的类型)实现组件属性类型的校验;
  • 默认属性

    • 通过组件的defaultProps来指定props的默认值。当组件属性未被赋值时,组件会使用defaultProps定义的默认属性。

4.组件样式

为组件添加样式的方法有两种:外部CSS样式表、内联样式

  • 外部CSS样式表

    • 引入CSS样式表的方式有两种:
      • 在HTML页面中通过标签href引入;

        这种方式常用于该样式文件作用于整个应用的所有组件

      • 把样式表文件作为一个模块,通过import引入;

        这种方式常用于该样式文件作用于某个组件(相当于组件的私有样式)

  • 内联样式

    • 内联样式实际是将CSS样式写到JS文件中,用JS对象表示CSS样式,然后通过DOM类型节点的style属性引用相应样式对象。
    • 内联样式的样式属性名必须使用驼峰格式的命名。

5.组件和元素

  • React元素:

    普通的JavaScript对象,这个对象通过DOM节点或React组件描述界面是什么样子的,JSX语法就是用来创建React元素的(JSX语法实际上是调用React.createElement方法);

  • React组件:

    React组件是一个class或函数,接收一些属性作为输入,返回一个React元素。

6.组件的生命周期

  • 挂载阶段

    组件被创建,执行初始化,并被挂载到DOM中,完成组件的第一次渲染

    • constructor
      通常用于初始化组件的state以及绑定事件处理方法;
    • componentWillMount
      在组件被挂载到DOM前调用,且只会被调用一次。在这个方法中调用this.setState不会引起组件的重新渲染。
    • render
      定义组件时唯一必要的方法,返回一个React的元素,用于描述组件的UI,注意:render并不负责组件的实际渲染工作,它只是返回一个UI的描述,真正的渲染出页面DOM的工作由React自身负责。render是一个纯函数,在这个方法中不能执行任何有福作用的操作,所以不能在render中调用this.setState,这会改变组件的状态。
    • componentDidMount
      在组件被挂载到DOM后调用,且只会被调用一次。这个方法通常会用于向服务器端请求数据,在这个方法中调用this.setState会引起组件的重新渲染。
  • 更细阶段

    组件被挂载DOM后,组件的props或state可以引起组件更新。无论props是否改变,父组件render方法每一次调用,都会导致组件更新。State引起组件更新,是通过调用this.setState修改组件state来触发的。
    组件更新阶段,依次被调用的生命周期方法:

    • componentWillReceiveProps(nextProps)

      • 这个方法只会在props引起的组件更新过程中,才会被调用。State引起的组件更新并不会触发该方法的执行。
      • 参数nextProps是父组件传递给当前组件的新的props;
      • 在componentWillReceiveProps中调用setState,只有在组件render及其之后的方法中,this.state指向的才是更新后的state。在render之前的方法shouldComponentUpdate、componentWillUpdate中,this.state依然指向的是更新前的state。
      • 调用setState更新并不会触发componentWillReceiveProps的调用(否则可能会进入一个死循环)
    • shouldComponentUpdate(nextProps, nextState)

      这个方法决定组件是否继续执行更新过程。当方法返回ture时,组件会继续更新过程;当方法返回false时,组件的更新过程停止,后续的componentWillUpdate、render、componentDidUpdate也不会再被调用。一般通过比较nextProps、nextState和组件当前的props、state决定这个方法的返回结果。这个方法可以用来减少组件的不必要的渲染,从而优化组件的性能。

    • componentWillUpdate

      这个方法在组件render调用前执行,可以作为组件更新发生前执行某些工作的地方,一般很少用到。
      shouldeComponentUpdate、componentWillUpdate中都不能调用setState,否则会引起循环调用问题,render将永远无法被调用,组件也无法正常渲染

    • render

    • componentDidUpdate(prevProps、prevState)

      组件更新后被调用,可以作为操作更新后的DOM的地方。这个方法的两个参数prevProps、prevState代表组件更新前的props和state。

  • 卸载阶段
    组件从DOM中被卸载的过程,这个过程中只有一个生命周期方法:

    • componentWillUnmount
      这个方法在组件被卸载前调用,可以执行一些清理工作,比如定时器、手动创建的DOM元素等。

** 只有类组件才具有生命周期方法,函数组件是没有生命周期方法的,因此永远不要在函数组件中使用生命周期方法 **

7.列表和keys

React使用key属性来标记列表中的每个元素,当列表数据发生变化时,React就可以通过key知道哪些元素发生了变化,从而只重新渲染发生变化的元素,提高渲染效率;

  • 一般使用列表数据的ID作为key值;
  • 如果列表包含的元素没有ID,也可以使用元素在列表中的位置索引作为key值;(但并不推荐使用索引作为key值,因为一旦列表中的数据发生重排,数据的索引也会发生变化,不利于React的渲染优化);
  • 虽然列表元素的key不能重复,但这个唯一性仅限于当前列表中。

8.事件处理

React中的事件是合成事件,并不是原生的DOM事件。React根据W3C规范定义了一套兼容各个浏览器的事件对象。

  • 在DOM事件中,可以通过处理函数返回false来阻止事件的默认行为,但在React事件中,必须显式地调用事件对象的preventDefault方法来阻止事件的默认行为。
  • 在某些场景下必须使用DOM提供的原生事件,可以通过React事件对象的nativeEvent属性获取。

在React元素中绑定事件的注意事项:

  • 在React中,事件的命名采用驼峰命名方式,而不是DOM元素中的小写字符命名方式;
  • 处理事件的响应函数要以对象的形式赋值给事件属性,而不是DOM中的字符串形式;

React事件处理函数的写法主要有以下三种方式:

  • 使用箭头函数

    直接在React元素中采用箭头函数定义事件处理函数。

    • 因为箭头函数中的this指向的是函数定义时的对象,所以可以保证this总是指向当前组件的实例对象;
    • 直接在render方法中为元素事件定义处理函数,最大的问题是,每次render调用时,都会重新创建一个新的事件处理函数,带来额外的性能开销,组件所处层级越低,这种开销就越大,因为任何一个上层组件的变化都可能触发这个组件的render方法。
  • 使用组件方法

    直接将组件的方法赋值给元素的事件属性,同时在类的构造函数中,将这个方法的this绑定到当前对象。例如

    • `this.handleClick = this.handlerClicke.bind(this)
    • onClick={this.handleClick}
      这种方式的好处是每次render不会重新创建一个回调函数,没有额外的性能损失。但在构造函数中为事件处理函数绑定this,代码有些繁琐。

    另一种方式,在为元素事件属性赋值时,同时绑定this,例如:
    onClick={this.handleClick.bind(this)}
    使用bind会创建一个新的函数,因此这种写法依然存在每次render都会创建一个新函数的问题,但需要处理额外传参时,这种写法有用武之地,例如:onClicke = {this.handleClick.bind(this, item)}

  • 属性初始化语法(property initializer syntax)

    使用ES7的property initializer 会自动为class中定义的方法绑定this。例如:handlerClicke = (event) => { …}
    这种方式既不需要在构造函数中手动绑定this,也不需要担心组件重复渲染导致的函数重复创建问题。

9.表单

受控组件和非受控组件

  • 受控组件
    只需根据组件的属性和状态渲染即可,状态全部由React控制的组件,称为受控组件;
    React采用受控组件技术,可以让一些非受控组件变为受控组件。
  • 非受控组件
    组件自身维护的一些状态,与用户操作相关,状态不受React控制的组件,称为非受控组件;

** 受控组件和非受控组件的区别 **

  • 受控组件保证了表单元素的状态统一由React管理,但需要为每个表单元素定义onChange事件的处理函数。
  • 非受控组件需要React中提供的特殊属性ref,来引用React组件或DOM元素的实例,defaultValue指定默认值,后续值由组件自己控制。
  • 非受控组件破坏了React对组件状态管理的一致性,往往容易出现不容易排查的问题,因此非特殊情况下,不建议使用。

三、React 16 新特性

1.render新的返回类型

React 16之前,render方法必须返回单个元素。现在,render方法支持两种新的返回类型:数组(由React元素组成)和字符串。
例如:

class ListComponent extends Component {
		render() {
		    return [
				<li key="A">First item</li>,
				<li key="B">Second item</li>,
				<li key="C">Third item</li>
			];
		}
}
class StringComponent extends Component {
	render() {
		return "Just a Strings";
	}
}

2.错误处理

React 16之前,组件在运行期如果执行出错,就会阻塞整个应用的渲染;React 16引入了新的错误处理机制,默认情况下,当组件中抛出错误时,这个组件会从组件树中卸载,从而避免整个应用的崩溃。React 16还提供了一种更加友好的错误处理方式——错误边界(Error Boundaries)。错误边界是能够捕获子组件的错误并对其做优雅处理的组件。优雅的处理可以是输出日志、显示出错提示等。
定义了componetDidCatch(error, info)这个方法的组件将成为一个错误边界。

3.Portals

React 16的Portals特性让我们可以把组件渲染到当前组件树以外的DOM节点上,典型的应用场景是渲染应用的全局弹框,使用Portals后,任意组件都可以将弹框组件渲染到根节点上,以方便弹框的显示。
Protals的实现依赖ReactDOM的一个新的API:
ReactDOM.createPortal(child, container)
第一个参数child:是可以被渲染的React节点,例如React元素、由React元素组成的数组、字符串等,第二个参数container:是一个DOM元素,child将被挂载到这个DOM节点上。

4.自定义DOM属性

React 16之前会忽略不识别的HTML和SVG属性,现在React会把不识别的属性传递给DOM元素。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值