## 说一下你对React的了解
1. React是一个Facebook出品的用于构建用户界面的JS库,只负责应用的视图层,帮助开发人员构建快速且交互式的web应用程序
2. React特点
(1) 声明式编程:它允许我们只需要维护自己的状态,当状态改变时,React可以根据最新的状态去渲染我们的UI界面;
(2) 组件化开发:将具有独立功能的UI模块封装成一个个组件,然后将其进行组合构建成一个完整的功能
(3) 多平台适配:
3. 采用虚拟DOM:数据进行变化时,采用diff算法将前后两次的虚拟DOM进行比较,只渲染更新的部分,减少了DOM操作,提升性能
4. JSX语法:js+xml,是 js 的语法扩展,编译后转换成普通的 js 对象。
5. 单向数据流:数据的流向只能从父组件通过props流向子组件;反之则不能,只能通过父组件传递过来的方法在子组件中调用来改变父组件中的数据
## 对JSX的了解以及为什么浏览器无法读取 JSX
1. JSX是JS+XML,是JS语法的扩展。但无法被浏览器读取,因为浏览器只能处理JS对象。只能通过babel将其转换为通过createElement方法创建出的对象,让浏览器识别
## JSX
1. JSX即Javascript + XML,JS语法的扩展,可以通过babel转换为createElement被浏览器识别。
2. 使用JSX的好处
(1) 解决使用createElement,若元素层级较深,则代码不易维护,可读性不强
3. 在结构中插入数据
(1) 基本类型
a. 字符串、数字:原样输出
b. 布尔值、null、undefined会被忽略,也就是不会被显示
(2) 引用类型
a. 数组:去掉逗号,直接输出
b. 对象:不支持对象的直接输出,但支持React.createElement()创建的对象的输出
c. 函数:不支持函数的直接输出,但支持函数调用的输出
4. 表达式
(1) 表达式:产生值的一组代码的集合,常见的有变量、运算符、函数调用、对象的属性调用
5. 条件渲染
(1) 与运算:左侧为真,输出右侧的值;左侧为false,直接返回false
(2) 或运算:左侧为假,输出右侧的值;左侧为真,直接返回true
(3) 三目运算符:条件为真,返回冒号左侧的值;否则返回冒号右侧的值
6. 列表渲染
(1) 批量渲染一组元素,做列表渲染是一定要添加key属性
(2) React进行条件渲染,就要将数据转换为一个数据,然后借助数组的方法进行列表渲染
a. 数组源头为对象:Object.keys(obj)返回一个由对象属性组成的数组,然后对这个数组进行遍历,通过obj[item]就可以拿到对象中的每一项数据了
7. JSX的注意事项
(1) class --> className
(2) for -->htmlFor
(3) style的值为一个对象
(4) 只有一个顶层元素,Fragment也可以作为一个顶层元素,作为一个包含容器,不会渲染在真实的DOM中
## React生命周期函数
1、Mounting 挂载阶段
constructor()、componentWillMount()组件挂载到页面之前、render()创建虚拟 DOM,进行
diff 运算,更新 DOM 树。不可进行 setState()、componentDidMount()组件挂载到页面之后,
可以在此请求数据
2、Updateing 更新阶段
componentWillReceiveProps()父级数据发生变化、shouldComponentUpdate()、性能优
化:这个函数只返回 true 或 false,表示接下来的组件是否需要更新(重新渲染)、返回 true
就是紧接着以下的生命周期函数,返回 false 表示组件不需要重新渲染,不再执行任何生命周期
函数(包括 render)、componentWillUpdate() 组件更新之前,不可进行 setState() 会导致函
数调用 shouldComponentUpdate 从而进入死循环、render()、componentDidUpdate()组件更新
之后
3、Unmounting 卸载阶段
componentWillUnmount 组件卸载和销毁之前立刻停用、可以在此销毁定时器,取消网络
请求,消除创建的相关 DOM 节点等
1. shouldComponentUpdate【性能优化周期函数】 是做什么的
(1) shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新绘制 dom,因
为 DOM 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优
化的 dom diff 算法,可以极大的提高性能
## React渲染流程
1. 执行render方法
2. 执行createElement创建虚拟DOM, 得到虚拟DOM树
3. 根据虚拟DOM树在界面上生成真实DOM
## React更新流程
1. props/state发生改变
2. render方法重新执行
3. 将JSX转换成createElement
4. 利用createElement重新生成新的虚拟DOM树
5. 新旧虚拟DOM通过'diff算法'进行比较
6. 每发现一个不同就生成一个mutation
7. 根据mutation更新真实DOM
## diff算法
(1) 原理:只比较同层同位置的元素,在比较过程中,同类型元素做修改;不同类型元素重新创建,若上一层是不同类型的元素,那么下一层不会进行比较,而是直接使用新的
## react中key的作用是什么
1. key是一个辅助标识,在同级元素中具有唯一性,用来追踪列表中哪些元素被修改。
列表渲染中添加key是为了保证在diff过程中元素的唯一性,从而减少不必要的重渲染,提升性能
2. 此外,react 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性
## react 中 refs 的作用是什么
1. Refs 是 react 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄,我们可以为
元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,该值会作为回调函数的
第一个参数返回
## 函数组件和类组件的区别
## 声明式编码与命令式编码
1. 声明式编码只需要关注结果就行,不用告诉做事的步骤
2. 命令式编码注重过程,告诉每一步执行的过程
3. 举例
比如说我想喝茶,你就会端一杯茶递给我,这就是声明式编码
命令式编码的方式是我想喝茶,你做事的过程:拿起杯子-->走到饮水机旁-->接水-->向我走过来-->把水递给我
## 为什么采用虚拟DOM
1. 主要还是为了提升性能,比如对DOM进行修改,页面进行渲染真实DOM和虚拟DOM的表现为
真实DOM的表现:渲染到页面上的是原来的真实DOM + 修改部分的真实DOM
虚拟DOM的表现:将修改之后的DOM与原来的DOM通过diff算法进行比较,只渲染有改动的地方
2. 虚拟DOM就是用JS对象表示DOM
## 脚手架create-react-app的使用
1. 全局安装:npm install -g create-react-app
2. 创建项目:create-react-app 项目名称
3. 进入项目:cd 项目名称
4. 启动项目:npm run start
## 函数组件和类组件的区别
1.
## props和state的区别
1. props用来接收父组件传递过来的数据,只读;state用来保存当前组件的数据,可以进行读写操作
2. state 状态,组件会随着状态的改变进行视图更新;状态修改时,可以调用组件的setState方法修改组件的状态
(1) 内部重新调用了render方法,生成新的虚拟DOM,然后完成组件视图的更新
(2) 不能直接修改state,虽然数据改变了但视图不会进行更新
## 组件传值
## 事件的this
## 组件通信
1. 父传子
(1) 在父组件的子组件中添加自定义属性,然后在子组件中通过props接受父组件传递过来的数据
2. 子传父
(1) 父组件中定义修改数据的方法,然后传递给子组件。在子组件中调用这个方法,通过函数传参的方式给父组件传递数据
3. 跨层级通信【Context】
(1) 通过React.createContext() 创建上下文对象,并从中解构出Provider和Consumer组件
(2) 在祖先组件中用Provider组件包裹后代组件,并用其value属性生产数据
(3) 消费数据【有三种方法】
a. 后代组件中通过Consumer组件消费数据【后代组件是函数组件、类组件均可】
b. 给后代组件添加静态属性contextType,指向创建的上下文对象;然后在后代组件中通过this.context.数据名来消费数据【后代组件是类组件】
c. 后代组件中使用useContext hook【后代组件是函数组件】
useConttext(参数)的用法:
a. 参数为创建的上下文对象【用来接收传递过来的信息】
b. 使用useContext hook相当于给类组件添加静态属性contextType
c. 就是react提供给函数组件的设置类属性这种方式来消费生产者生产的数据的
d. 接受一个context对象,并返回该context的当前值。当前的context值是由上层组件中距离当前组件最近Provider的value属性提供的。只能用在函数组件中
(4) Context可以定义创建多个上下文对象,相应的Provider和Consumer嵌套使用
## contextType和useContext的区别
1. contextType用于类组件中,且只能订阅单一的context来源。创建多个上下文对象时,不能使用该方法。因为后面添加的contextType属性会覆盖前面的
2. useContext用于函数组件和自定义hook中,可以订阅多个context来源
## 尽量少用Context
1. 因为比较消耗性能。执行setState之后,所有的子组件要全部更新。
2. 使用Context传递的数据为什么要放在state中呢
(1) 因为state是响应式的,比如修改主题色时执行setState组件就会进行更新。如果定义一个全局变量,对主题色进行修改后组件不会进行更新
一旦Provider中的属性值修改之后,就要求所有的子组件都进行更新,但页面更新比较消耗性能,所以Context要慎用
3. 使用Context考虑的两个因素
(1) 组件是否跨层级通信
(2) 祖先组件的状态发生变化时,后代组件是否都要进行更新
## context与redux的区别
1. context是祖先组件与子孙组件的跨层级通信;redux更多是数据共享,组件之间没有明显的层级关系,可能是并列的
2. context传递的参数值发生变化时,所有的后代组件都要进行更新。
redux也是,只要state发生改变,所有子组件都要进行更新。
## 使用context的注意事项【引用类型放state】
1. 若祖先组件提供给后代组件的数据是对象形式的,则不要直接写在Provider的value属性中,要将value状态提升到父节点的state中
(1) Provider是一个组件的形式,但是放到DOM结构中只处理逻辑,并没有真实的DOM节点。后面进行diff时,将原来的value值和变化之后的value值相比,则永远不会相等,所以子组件要不断地进行更新,消耗性能。若将value状态提升到父节点的state中,进行diff时将原来的value值和变化之后的value值相比,相等时,子组件不用进行更新;不等时,则会进行更新
## 高阶组件
1. 高阶组件就是一个函数,这个函数的参数是一个组件,返回一个新组件
## 高阶组件todo
1. 链式调用
2. 装饰器写法
(1) 配置craco、antd、less
(2) 配置装饰器
3. 注意事项
## 组件化优点
1. 增强代码复用性,提升开发效率
2. 简化调试步骤,提升项目的可维护性
3. 便于协同开发
4. 注意点:降低耦合性