1. 箭头函数内的 this 指向函数定义时所在的上下文对象,而不是函数执行时所在的上下文对象。
2. 引入 rest 参数(形式为 ...变量名)用于获取函数的多余参数,来代替 arguments 对象的使用。rest 参数是一个数组,数组织中的元素是多余的参数。注意,rest 之后不能有其他参数。
function languages(lang, ...types){ console.log(types); } languages('JavaScript', 'Java', 'Python'); //["Java","Python"]
3. 扩展运算符:是三个点(...),它讲一个数组转化成用逗号分隔的参数序列,类似于 rest 参数的逆运算。
function sum(a, b, c){ return a + b + c; } let numbers = [1, 2, 3]; sum(...numbers); //6
4. 组件的生命周期:组件从创建到被销毁的过程称为组件的生命周期。React 为不同的生命周期阶段提供了不同的生命周期方法,让开发者更好的控制组建的行为。组建的生命周期被分为三个阶段:挂载阶段,更新阶段和卸载阶段。
4.1 挂载阶段:组件被创建,执行初始化,并被挂载到 DOM 中,完成组建的第一次渲染,用到的生命周期方法有:constructor,componentWillMount,render, componenDidMount。
constructor:这是ES 6 class 的构造方法,组件被创建时,会首先调用组件的构造方法。这个构造方法接收一个 props 参数,props 是从父组件中传入的属性对象,如果父组件中没有传入属性而组件自身定义了默认属性,那么这个 props 指向的就是组件的默认属性。你必须在这个方法中首先调用 super(props) 才能保证props被传入组件中。constructor 通常用于初始化组件的state以及绑定事件处理方法等工作。
componentWillMount:这个方法在组件被挂载到DOM前调用,且只会被调用一次。这个方法在实际项目中很少会用到,因为可以在该方法中执行的工作都可以提前到 constructor 中。在这个方法中调用 this.setState 不会引起组件的重新渲染。
render:这是定义组件时唯一必要的方法(组件的其他生命周期方法都可以省略)。在这个方法中,根据组件的props和state返回一个React元素,用于描述组件的 UI,通常 React 元素使用JSX语法定义。需要注意的是,render 并不负责组件的实际渲染工作,它只是返回一个UI的描述,真正的渲染出页面DOM的工作由React自身负责。render 是一个纯函数,在这个方法中不能执行任何有副作用的操作,所以不能在 render 中调用 this.setState,这会改变组件的状态。
componentDidMount:在组件被挂载到 DOM 后调用,且只会被调用一次。这时候已经可以获取到 DOM 结构,因此依赖 DOM 节点的操作可以放到这个方法中。这个方法通常还会用于向服务器端请求数据。在这个方法中调用 this.setState 会引起组件的重新渲染。
4.2 更新阶段:组件被挂载到 DOM 后,组件的 props 或 state 可以引起组件更新。props 引起的组件更新,本质上是由渲染该组件的父组件引起的,也就是当父组件的 render 方法被调用时,组件会发生更新过程,这个时候,组件 props 的值可能发生改变,也可能没有改变,因为父组件可以使用相同的对象或值为组件的 props 赋值。但是,无论 props 是否改变,父组件 render 方法每一次调用,都会导致组件更新。State 引起的组件更新,是通过调用 this.setState 修改组件 state 来触发的。组件更新阶段,依次调用的生命周期方法有:componnentWIllReceiveProps,shouldComponentUpdate,componentWillUpdate,render, componentDidUpdate
componentWillReceiveProps:组件初始化时不调用,组件接收新的props (不管这个 props 是不是和原来的相同,都会接收)时调用。目前不推荐使用。
shouldComponentUpdate:这个方法决定组件是否继续执行更新过程。当方法返回 true 时(true也是这个方法的默认返回值),组件会继续更新过程;当方法返回 false 时,组件的更新过程停止,后续的 componentWillUpdate、render、componentDidUpdate 也不会再被调用。一般通过比较 nextProps、nextState 和组件当前的 props、state 决定这个方法的返回结果。这个方法可以用来减少组件不必要的渲染,从而优化组件的性能。
componentWillUpdate:这个方法在组件 render 调用前执行,可以作为组件更新发生前执行某些工作的地方,一般也很少用到。
注意:shouldComponentUpdate 和 componentWillUpdate 中都不能调用 setState,否则会引起循环调用问题,render 永远无法被调用,组件也无法正常渲染。
componentDidUpdate(prevProps,prevState):组件更新后被调用,可以作为操作更新后的 DOM 的地方。这个方法的两个参数 prevProps、prevState 代表组件更新前的 props 和 state 。
4.3 卸载阶段:组件卸载阶段只有一个生命周期的方法被调用:componentWillUnmount,这个方法在组件被卸载前调用,可以在这里执行一些清理工作,比如清除组件中使用的定时器,清除componentDidMount中手动创建的DOM元素等,以避免引起内存泄漏。
最后注意:只有类组件有生命周期方法,函数组件没有生命周期方法,因此,永远不要在函数组件中使用生命周期方法。
5. 组件 state:组件state必须能代表一个组件 UI 呈现的完整状态集,即组件的任何 UI 改变都可以从state的变化中反映出来;同时,state 还必须代表一个组件UI呈现的最小状态集,即 state 中的所有状态都用于反映组件 UI 的变化,没有任何多余的状态,也不应该存在通过其他状态计算而来的中间状态。state和props又有什么区别呢?state和props都直接和组件的UI渲染有关,它们的变化都会触发组件重新渲染,但props对于使用它的组件来说是只读的,是通过父组件传递过来的,要想修改props,只能在父组件中修改;而state是组件内部自己维护的状态,是可变的。总结一下,组件中用到的一个变量是不是应该作为state可以通过下面的4条依据进行判断:
(1)这个变量是否通过props从父组件中获取?如果是,那么它不是一个状态。
(2)这个变量是否在组件的整个生命周期中都保持不变?如果是,那么它不是一个状态。
(3)这个变量是否可以通过其他状态(state)或者属性(props)计算得到?如果是,那么它不是一个状态。
(4)这个变量是否在组件的render方法中使用?如果不是,那么它不是一个状态。这种情况下,这个变量更适合定义为组件的一个普通属性。
5.1 state 的更新是异步的:调用setState时,组件的state并不会立即改变,setState只是把要修改的状态放入一个队列中,React会优化真正的执行时机,并且出于性能
原因,可能会将多次setState的状态修改合并成一次状态修改。所以不要依赖当前的state,计算下一个state。当真正执行状态修改时,依赖的this.state并不能保证是最新的state,因为React会把多次state的修改合并成一次,这时this.state还是这几次state修改前的state。另外,需要注意的是,同样不能依赖当前的props计算下一个状态,因为props的更新也是异步的。
6. 组件通信:
6.1 组件挂载阶段通行:componentDidMount是执行组件与服务器通信的最佳地方,原因主
要有两个:
(1)在componentDidMount中执行服务器通信可以保证获取到数据时,组件已经处于挂载状态,这时即使要直接操作DOM也是安全的,而componentWillMount无法保证这一点。
(2)当组件在服务器端渲染时(本书不涉及服务器渲染内容),componentWillMount会被调用两次,一次是在服务器端,另一次是在浏览器端,而componentDidMount能保证在任何情况下只会被调用一次,从而不会发送多余的数据请求。
7. 路由:一般在项目中建立两个文件夹,非路由组件文件夹(components)和路由组件文件夹(pages 或者 views)。
7.1 嵌套路由的写法:a. 编写路由组件;b. 在父路由中指定路由链接 <NavLink> 或 <Link> 和 路由 <Route>。注意在导入组件的时候,注意区分默认组件和普通组件的导入方法的不同,一旦混淆两者的导入方法,就会报错。
7.2 路由通信(路由组件之间传递数据):子路由接收的是一个 params 参数。该参数在 path 中,冒号后面的内容就是参数。Route 中的 path 会和 link 里面的 to 比较得出参数 parmas。那么子路由的内容,可以通过读取不同的 params 值,来显示,不同的内容。
8. redux: