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 也行(不推荐)

浙公网安备 33010602011771号