1、Component,Element,Instance之间有什么区别和联系
- 组件(component):
一个组件Component可以通过多种方式声明,可以是带有一个render() 方法的类,也可以是带有rturn的函数。这两种组件都可以把属性props作为输入,把返回的一颗元素树作为输出
- 元素(Element):
一个元素element是一个普通对象,他描述一个组件实例和它所要求的属性,或者一个DOM节点和它所要求的属性。它仅仅包含以下有关信息:
✨组件类型type (比如,这是一个按钮 Button
)
✨属性props (比如,它的颜色 color
)
✨它所包含的若干个子元素children
createElement
可以
让你创建一个 React 元素。它可作为编写 JSX 的替代方法。
代码:
import { createElement } from 'react';
function Greeting({ name }) {
return createElement(
'h1',
{ className: 'greeting' },
'Hello'
);
}
- 实例(Instance):
一个实例Instance是你在类组件中使用关键字this所指向的东西。他用来存储本地状态和响应生命周期函数。函数组件根本没有实例。类组件有实例,
---------------------------------------------------------------------------------------------------------------------------------
2、React.createClass和extends Component的区别有哪些?
这两种方法都是用来创建类,前者使用来调用React.createClass方法创建类,后者则是使用了ES6的语法创建类。
两者主要的区别:
- 语法的区别
- propType和getDefaultProps的区别
- State的区别
- this的区别
- Mixins的区别
✨语法区别:
React.createClass:
import React from 'react';
const Contacts = React.createClass({
render() {
return (
<div></div>
);
}
});
export default Contacts;
React.components:
import React from 'react';
class Contacts extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div></div>
);
}
}
export default Contacts;
这两种在语法上的差别主要体现在方法的定义和静态属性的声明上。
1️⃣. crateClass方式的方法定义要使用逗号隔开,因为createClass本质是一个函数,给他传递的是一个对象。
2️⃣. React.components定义方法时不需要用逗号隔开。符合Es6的语法。
3️⃣. crateClass方式的方法定义要使用function关键字
4️⃣. React.components定义方法时不需要function关键字。
✨propTypes和getDefaultProps的区别:
1️⃣. 在React.createClass中getDefaultProps属性是一个返回Object来创建初始的props和获取props的函数,
propType:在React.createClass中propTypes则是一个对象,用来设置prop的类型
getDefaultProps(){
return{
};
}
propTypes:{
name: React.PropTypes.string
},
2️⃣.在React.Component中,propTypes和defaultProps则是作为组件实例类的属性
组件名.propTypes = {
};
组件名.defaultProps = {
};
❗❗❗:在React.Components中,getDefaultProps已经更名为defaultProps
✨this的区别:
React.component:由于使用了ES6,属性不会自动绑定到React类的实例上,需要通过bind来绑定this。
React.createClass会自动绑定this
✨状态的区别:
React.createClass通过genInitState方法返回一个包含初始值的对象
React.component通过constructor设置初始状态
---------------------------------------------------------------------------------------------------------------------------------
3、React高阶组件是什么,和普通组件有什么区别,使用什么场景
React高阶组件就是一个函数,且该函数接收一个组件作为参数,并返回一个新的组件,它只是一种组件的设计模式,这种设计模式是由react自身的组合性质必然产生的。我们将他称为纯组件,因为它们可以接收任何动态提供的子组件,但他们不会修改或复制其输入组件中的任何行为。
✨高阶组件和普通组件的区别:
高阶组件是将接收到props转化为另外一个新组件,普通组件则是将接收到的props转化为UI
✨高阶组件使用场景:
1️⃣:权限的控制:利用高阶组件的条件渲染特性可以对页面进行权限控制,权限控制一般分为两个维度:页面级别和页面元素级别:
代码演示:
function withAdminAuth(WrappedComponent){
const nav = useNavigate()
const getAdminToken = async()=>{
const result = await $api.login().verifyAuth()
if(result.code == 401){
message.warning('身份已过期请重新登录')
}
}
useEffect(() => {
getAdminbyToken()
}, [])
if(getToken(TOKEN_KEY)){
return (
<div>
</WrappedComponent>
</div>
}
}
2️⃣:路由跳转使用高阶组件
import { useNavigate, useSearchParams, useLocation, useParams } from 'react-router-dom'
function withRouter(WrapComponent) {
return (props) => {
console.log('props', props);
const params = useParams()
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const location = useLocation()
return <WrapComponent {...props}
navigate={navigate}
params={params}
query={searchParams}
location={location}
></WrapComponent>
}
}
export default withRouter
---------------------------------------------------------------------------------------------------------------------------------
4、对componentWillReceiveProps的理解
子组件在第一次收到props时不执行componentWillReceiveProps()钩子函数,该钩子函数接收一个参数props,该参数是第二次收到的props。
当父组件调用this.setState(nextProps)更新组件状态时,父组件重新渲染,子组件接收到新的props,componentWillReceiveProps(nextProps)这时被调用。
使用好处:在这个生命周期中,可以在子组件的render函数执行前获取新的props,从而更新子组件自己的state,可以将数据请求放在这里执行,需要传的参数则从componentWillReceiveProps(nextProps)中获取。而不必将所有的参数都放在父组件中。于是该请求只会在该组件渲染时才会发出
5、那些方法会触发React重新渲染,重新渲染render会做些什么?
1️⃣.那些方法会触发React重新渲染:
- setState()方法被调用
❗❗❗:执行setState的时候不一定会重新渲染,当setState传入null时,并不会触发render.
- 父组件重新渲染
只要父组件重新渲染了,即使传入自组件的props未发生变化,那么子组件也会重新渲染,进而触发子组件的render.
-函数组件:则调用useState,或者子组件调用 useReducer 返回触发dispatch(action),
2️⃣.重新渲染render会做些什么?
- 会对新旧VNode进行对比,也就是所说的Diff算法
- 对新旧两颗DOM数进行一个深度的遍历,这样每一个节点都会有一个标记,在到深度遍历的时候,每遍历一个节点,就把该节点和新的节点树进行对比,如果有差异就放到一个对象里面
- 遍历差异对象,根据差异的类型,根据对应规则更新VNode