React考点

2. 项目如何从0-1 

* 架构
* 用react-cli 还是自己搭建webpack

3. 如何通过webpack搭建脚手架工具

* 入口
* 出口
* 插件
* loader 加载器

4. react15版本和16版本有什么区别

* 生命周期的改变
* 组件创建方式的改变
* 渲染方式的改变

5. 生命周期的改变

6. 组件创建方式的改变

React.createClass()
class Component extends Component{}

7. 渲染方式的改变

8. 组件的分类

a、函数组件 无状态组件 木偶组件 ui组件
import React from 'react';
function FunComponent(props){
return(
<div>
{props.name}
函数组件
无状态组件
ui组件
傻瓜组件
</div>
)
}
export default FunComponent

b、类组件 有状态组件 智能组件 功能组件
import React, { Component } from 'react';
class ClassComponent extends Component {
state = { name:"类组件" }
render() {
return (
<div>
类组件
有状态组件
智能组件
容器组件
</div>
);
}
}
export default ClassComponent;

c、受控组件
表单的value 被state 值控制 无法直接修改,要通过setState进行修改

d、非受控组件
通过ref 获取表单的数据

e、高阶组件

9. react数据承载类型

a、props 来自于组件外部 在组件内部只能使用不能修改
b、state 属于组件内部 可以进行修改

10. 单向数据流

数据只能从外向里,而不能从内部流向外部

11. 如何修改state值

setState()

12. 如何理解setState这个api,setState有什么特点

* react数据更新页面不会渲染 需要通过setState 触发render的再次执行
* setState 是一个异步函数
* setStete 参数1 更改的数据 参数2 是修改成功的回调
* setState在使用的时候会进行合并操作,同步操作中连续执行setState只会执行一次render
* 在异步操作中执行多次setState(变成同步) 每次都会执行render

13. react 中如何绑定该数据

* 插值法 {}
* 插值法不能放对象
* 条件渲染 列表渲染map 属性绑定className 事件绑定 onClikc={this.test.bind(this,参数)}

 

14. Fragment

react 提供的一个组件 作为容器使用 页面不会进行渲染

15. 如何实现组件通信

父子通信: props(属性) ref
子父通信: props (方法)
兄弟通信: 状态提升 context上下文 全局状态管理

16. 什么叫状态提升

将state放到公有父元素上 结合父子与子父实现通信

17. context上下文是什么?怎么用?解决了什么问题

* 定义:跨组件通信

* 创建上下文对象
import React from 'react'
export const NameContext = React.createContext(null)

* 通过上下文对象在父组件注册一个数据
import {NameContext} from './NameContext.js'

<NameContext.Provider value={ this.state.name}>
<div style={this.state.style}>
<h1>Box</h1>
<button onClick={this.changeName.bind(this,'李雷雷')}>改名</button>
{this.state.name}
<Frather></Frather>
</div>
</NameContext.Provider>

* 在子组件(任何一个子组件)将上下文对象挂载到 该组件静态属性contextType上 就可以使用父组件提供的值
import {NameContext} from './NameContext'

static contextType = NameContext

<div style={this.state.style}>
<h1>Son</h1>
{this.context}
</div>

18. 如何实现在嵌套的子组件里修改上下文数据

* Consumer上下文对象的api
* 用Consumer 组件包裹要渲染的组件
* 用Consumer组件里渲染一个函数
* 函数的参数就是在父组件提供的 数据
<NameContext.Provider value={ {name:this.state.name,toggleName:this.changeName} } >
<div style={this.state.style}>
<h1>Box</h1>
<button onClick={()=>{
this.changeName('李雷雷')
}}>改名</button>
{this.state.name}
<Frather></Frather>
</div>
</NameContext.Provider>

* 在Consumer函数里返回要渲染的jsx
<NameContext.Consumer>
{/* 回调函数的参数就是provider提供的数据 */}
{({name,toggleName})=>{
return(
<div style={this.state.style}>
<h1>Son Consumer</h1>
{name}
<button onClick={()=>{
toggleName('贞子')
}}> 改名</button>
</div>
)
}}
</NameContext.Consumer>

19. bind


a、bind 是函数原型上的方法,对于函数来说 谁执行的函数 this 指向的就是谁
b、原理:改变一个函数的this指向,将函数放在目标对象的内部作为内部方法

Function.prototype.myCall=function(context){
console.log('手写call方法')
console.log(context) //传递的对象
console.log(this) // 执行call函数的方法
context = context||window //如果参数不传默认指向window对象
context.fun = this
context.fun()
}

20. react有哪些生命周期

初始化
getInitialState (15.6)
getDefaultProps (15.6)
contrustor 构造函数(16)
state 初始化数据(16)
挂载
componentWillMount (17废弃)
componentDidMount
更新
componetWillUpdate (17废弃)
componentDidUpdate
销毁
componentWillUnmont
数据改变
componentWillReceiveProps (17废弃)
shouldComponentUpdate


21. react中常用哪些生命周期,都用来干什么

contrustor/state 初始化数据
componentDidMount 来做副作用(网络请求...)
componentWillUnmont 擦屁股 销毁全局监听计时器 ...
shouldComponentUpdate 控制render函数是否执行

22. react fiber算法相关 (分片)
* react中副作用放在哪个生命周期里
componentDidMount

* 副作用为什么不放在componentWillMount里
有可能会被打断,不断重新执行

* 生命周期有哪些变化
* react15版本和16版本渲染机制有哪些差异
* 是否听说过同步渲染和异步渲染
* 是否了解过react fiber
* react新增哪些生命周期

react 15版本之前渲染方式是同步渲染 导致页面的卡顿
16版本之后渲染核心引入fiber 异步渲染
fiber 将一个时间超长任务分段 解决页面卡顿问题

fiber 的异步渲染分成2个阶段:

第一个阶段:可以被其他优先级高任务打断, render之前的生命周期都可以被打断 ,打断之后就会重新执行
componentWillMount (17版本废弃)
componponetWillReceiveProps (17版本废弃)
componentWillUpdate (17版本废弃)
getDerivedStateFromProps 数据变化的时候触发(新增)
getSnapshotBeforeUpdate 更新前触发(新增)
shouldComponentUpdate 控制render函数是否执行

第二阶段 :不会被打断, render 之后的生命周期都是第二阶段

注意点:组件渲染过程中 子组件挂载总是优先于父组件

23.两个新增的生命周期

a、getDerivedStateFromProps 数据变化的时候触发
(代替componponetWillReceiveProps)

1. 不能和已经废弃的生命周期一块用
2. 这是个静态函数 static
3. 必须return 值
4. 在初始化之后 渲染之前 执行一次 (类似于 willmount)
5. 数据(props state)改变之后也会执行(类似于 WillReceiveProps)
6. 生命周期内部不能获取当前组件对象 没有this
7. 参数一 是props 参数二 是state
参数props和state 是将要变成的值,改变后的值
8. 返回值 如果null 按照参数里的数据进行更新界面
9. 返回值是一个对象 按照返回值来更新界面

static getDerivedStateFromProps(props,state){
console.log('getDerivedStateFromProps')
console.log('statea.age',state.age)
if(state.age<10){
return null
}else{
return {age:999}
}
}

注意点:
静态函数 静态属性
静态 只有在类的内部可以调用 类的实例不能调用
其他的动态函数 类内部可以调用 实例也可以调用

b、getSnapshotBeforeUpdate 获取更新之前的快照
(代替componentWillUpdate)

1.不能和已经废弃的生命周期同时使用
2.必须和componentDidUpdate 配对使用
3.能访问this对象 this.state和this.props 里存放的是修改后的数据
4.参数props和state 里存放的是修改前的数据
5.return的值会作为componentDidUpdate 第三个参数使用

getSnapshotBeforeUpdate(props,state){
console.log('getSnapshotBeforeUpdate')
console.log('this',this.state.age)
console.log('参数',state.age)
return {xixi:'xixi'}
}
componentDidUpdate(props,state,snapshot){
console.log('componentDidUpdate')
console.log('snapshot',snapshot)
}

24. 在react组件渲染中做过哪些优化
shouldComponetUpdate 控制组件是否重新render
<PureComponent> 浅比较
class Box extends PureComponent {}

25. 是否了解过hooks
增强函数组件,让函数组件可以使用类组件的功能(比如有状态和生命周期)

a、useState 给函数组件赋予state的功能
函数组件本身只能使用 props 而且不能修改 所以函数组件只能做渲染作用,userState 这一个hook 赋予了函数组件state的功能 可以在函数组件里修改数据

语法:let [变量名,修改这个变量的方法] = useState(变量的初始值)
let [age,setAge] = useState(15)
let [name,setName] = useState('韩梅梅')

b、useEffect 给函数组件赋予生命周期的功能( 挂载 更新 销毁)

1.useEffect 本是一个函数 参数是一个回调
2.当页面挂载的时候会执行一次回调 相当于类组件里挂载的生命周期
3.发生更新操作的时候也会执行 相当于组件里更新的生命周期
4.组件销毁的时候触发 回调函数里return的函数相当于销毁的生命周期
5. useEffec 第二个参数是一个数组 控制那些state可以触发更新的生命周期

// 组件的挂载和销毁
useEffect(()=>{
console.log('组件挂载了')
return()=>{console.log('组件销毁了')}
},[])

// name、age更新触发
useEffect(()=>{
console.log('name或者age更新了')
},[name,age])

c、userContext 在函数组件里获取上下文

function UseContextDemo(){
let value = useContext(ColorContext)
return(
<div>
<h1>UseContextDemo</h1>
{value}
</div>
)
}

<ColorContext.Provider value='hehe'>
<div>
<h1>Box</h1>
<hr/>
<UseContextDemo></UseContextDemo>
</div>
</ColorContext.Provider>

26. 路由
* hash(哈希) 和历史路由的区别
* 路由的实现原理
* 监听地址栏的改变
* 根据地址栏的改变渲染组件
* 线上hash路由和历史路由的区别 刷新之后会404
重定向redirect 精准匹配 万里挑一switch 高阶组件withRouter 路由传参 声明导航 和编程导航 路由对象 嵌套路由
push replace go goback goforwd

27. 全局状态管理 redux
* 你在什么地方用过全局状态管理 (多组件共享状态 一个组件发生改变其他组件跟着变)
* 怎么使用的全局状态管理 全局状态管理的使用流程
* 创建全局状态管理对象 store
* 创建reducer
reducer 本质是一个纯函数 接受修改前的数据 和actions参数
在函数的内部根据 action 对修改前的数据进行修改 返回新新数据
* 将store对象和reducer 进行关联
* 在页面上通过 Store的getState 获取全局状态值
* 用户在组件里触发 actionCreator的方法 创建action 通过dispath 发送给reducer
* 在需要更新的组件里做subscribe监听 控制组件重新渲染

28. 什么叫纯函数
输出只由输入决定

29. 使用全局状态管理的时候,应该注意什么
在reducer里注意不能修改原数据(引用类型),导致页面不更新

30. 不能修改原数据的解决方式是什么
深拷贝: JSON.stringIfy JSON.Parse() 、自己去递归遍历、 第三方插件 immutable
浅拷贝: Object.assign() 、 扩展运算符

31. react-redux
简化redux的使用

32. 是否了解过react-redux 的实现原理
通过高阶组件hoc 和上下文context 对redux 使用进行优化
connect(mapStateToprops,mapDispathToProps)

33. 你在使用全局状态管理的时候如何处理异步问题
异步中间件 redux-thunk redux-sage redux-promise ...

34. 全局状态管理中将网络请求放在那里
1. 放在组件
2. 放在actions (vue就叫action react中叫actionCreator)

35. 异步请求放在actions里的好处
1.便于统一管理请求 减少冗余代码
2.时间旅行 可以检测到数据的变化

36. 听过hoc ? 项目中如何做代码优化 ? hoc都在哪些地方使用?
高阶组件本身就是一个函数 接受一个组件作为参数 返回一个新的组件
被高阶组件处理过的组件 一般在props里获取数据

代码优化:
可以通过高阶组件封装公有代码、 路由拦截器 、 路由懒加载 react-loadable 、withRouter

37、同步任务、异步的宏任务、异步的微任务

同步:普通的js代码、new Promise本身
宏任务:setTimeout的回调、 setInerval的回调
微任务:Promise的resolve的回调then、reject的回调catch
事件循环 event loop:主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)

执行顺序
1、先执行主线程的同步操作,异步放到任务队列
2、主线程执行完之后,会读取任务队列中的事件并执行,微任务执行优先级高于宏任务,如果遇到异步,放到任务队列(之前的已清空)
3、不断重复2,直到任务结束

38. 虚拟dom
本质是一个对象 该对象和真实dom有相同的结构和属性

39. diff 算法
数据发生改变 引起虚拟dom改变 对比修改前后2次虚拟dom 寻找出差异点 根据差异点更新真实dom

原始 diff算法 复杂度 O(n^3)

react 优化的diff算法 复杂度 O(n)
1. tree Diff 元素禁止跨树的层次对比(同层次对比)
2. component Diff 对比是不是同一类型的元素,不同就整个删除,相同就复用(更新有改变的属性)
3. element Diff

新Vdom有的,老Vdom没有 新建元素
老Vdom有的,新Vdom没有 删除元素
老Vdom有的,新Vdom也有 复用,移动元素

40. key的作用
用来优化diff算法的效率,解决数据列表

41. 使用什么作为一个key
推荐使用唯一不重复 不会变的值作为key:主键_id
但是在循环中 不涉及到数组下标变化的 用index 也行(不推荐)

posted @ 2020-04-19 22:26  ImbaCOOL  阅读(301)  评论(0)    收藏  举报