上篇:【react】react18的学习(一)
本篇内容:函数组件、插槽实现、类组件
命名:大驼峰;
传props值:同普通标签,除字符串,用{}
形式传递;
接收props值:
渲染:
babel-preset-react-app
将标签转为React.createElement()
;React.createElement()
处理函数标签,先执行将props传入函数,然后执行函数,生成虚拟DOM;root.render()
,渲染成真实DOM;props 介绍
+ 在组件被解析成虚拟DOM后,标签上的属性和子标签就被放在虚拟DOM对象的props里了;
+ props对象被冻结,只读;
+ 用于父子传值;
+ 校验功能:import PropTypes from 'prop-types'
+ 插槽功能: let { children } = props
// 插槽
import React from 'react';
let { children } = props
// 默认children可能为数组[](传多标签)、对象{}(传单标签)、字符串""(传值)
// 使用React.Children,不会改变props中的children
children = React.Children.toArray(children)
console.log(children);//转为数组
// 具名插槽如下图
// views/Demo.jsx
// package.json中配置自动引入
// import React from 'react';
import PropTypes from 'prop-types'
// props 初始值
Demo.defaultProps = {
age: 10
}
// props 校验
Demo.propTypes = {
title: PropTypes.string.isRequired,
age: PropTypes.number
}
export default function Demo(props) {
console.log(props);
let { title, age, style, children } = props
age = 19
return (
<div style={style}>
年龄:{age},标题:{title}
{children}
</div>
);
}
---------------------------------------------------------------------------------
// 入口文件:index.jsx
import Demo from './views/Demo'
root.render(
<Demo title={'aa'} age={18} style={{ color: 'red' }}>
<span>123</span>
<span>456</span>
</Demo>
)
// babel解析
React.createElement(
Demo,
{
age: 10,
style: {
color: "red"
}
}
);
// React.createElement()执行,生成虚拟DOM
{
$$typeof:Symbol(react.element)
key:null,
ref:null,
type: f Demo(),
props:{
age:10;
style:{
color:"red"
}
},
...
}
1、通过React.Component.call(this)
,给实例赋私有属性:props、refs、context、updater
2、将类的原型对象的原型链指向:Parent.prototype.__proto__ == Reaact.Component.prototype
,这样实例可以沿着原型链访问;
getDefaultProps
:初始化属性、进行属性校验、执行rendergetInitialState
:初始化状态 state,在实例上挂载,默认null(没有双向绑定,没有响应式set,状态更改不会自动更新视图,需要使用官方组件原型上的方法:this.setState()、this.state + this.forceUpdate()
)UNSAFE_componentWillMount
render函数
,触发子组件渲染,返回虚拟Dom,并开始渲染(不是root.render()方法,这个方法没有返回值,是入口文件用于触发组件)componentDidMount
,可以获取真实Dom方式一:组件state触发更新
shouldComponentUpdate(nextProps, nextState, nextContext)
,通过强制更新组件直接跳过该周期函数;UNSAFE_componentWillUpdate(nextProps, nextState, nextContext)
render
,就是最初写的,触发子组件更新渲染componentDidUpdate(preProps, preState, snapshot)
方式二:父组件重新渲染,从而更新子组件
UNSAFE_componentWillReceiveProps(nextProps, nextContext)
最后一个生命周期8: componentWillUnmount
:父组件销毁,先销毁子组件;
类组件的首次渲染
getDefaultProps:初始化属性
getInitialState:初始化状态
UNSAFE_componentWillMount:挂载前
render:渲染生成虚拟DOM
componentDidMount:挂载后,可获取真实DOM
// 类组件的更新
shouldComponentUpdate:是否更新
UNSAFE_componentWillUpdate:更新前
render:渲染生成虚拟DOM
componentDidUpdate:更新后
UNSAFE_componentWillReceiveProps:父组件触发子组件更新
componentWillUnmount:销毁前
shouldComponentUpdate:是否更新
受控组件:通过修改状态更新视图
非受控组件:通过获取真实DOM更新视图;
原生元素真实DOM:三种方式
可在
生命周期 componentDidMount(){}、componentDidUpdate(preProps,preState)()
<div ref='vote'>
----
this.refs.[ref名]
<div ref={x => this.box = x}>
---
this.box
Ref对象
(推荐)// 生成Ref对象
box = React.createRef()
// 类原型上的方法(类原型上加属性只能用prototype)
render() {
return (
<div ref={this.box}>
----
this.box.current
组件标签上的 ref:
// 类组件:获取实例
<Demo1 ref={x => this.child1 = x} />
// 函数组件:获取某个元素
<Demo2 ref={x => this.child2 = x} />
----
const Demo2 = React.forwardRef((props, ref) => {
return (
<div ref={ref}></div>
);
})
函数组件:渲染块,机制简单,静态组件;
类组件:功能强大,渲染慢,动态组件;
hooks组件:对函数组件的改造;