1. 组件通讯介绍
2. 组件的 props
// 导入react
import React from "react";
// 创建组件
// 函数组件接受组件的数据
// function Hello(props){
// console.log(props.name);
// }
// 类组件接收组件的数据
class Hello extends React.Component{
constructor(props){
super(props)
// 必须要传props给super() 不然constructor里面拿不到props数据
console.log(props);
}
render(){
return (
// props 是一个对象
<p>{this.props.name}</p>
)
}
}
// 将组件暴露出去
export default Hello
3. 组件通讯的三种方式
3.1 父组件传递数据给子组件
3.2 子组件传递给父组件
3.3 兄弟组件
// 导入react
import React from "react";
// 创建父组件
class Counter extends React.Component{
state = {
// 提供状态
publicData:0
}
// 提供修改状态的方法
sendData=()=>{
this.setState({
publicData:this.state.publicData+1
})
}
render(){
return (
<div>
<Child1 data = {this.state.publicData}></Child1>
<Child2 sendData={this.sendData}></Child2>
</div>
)
}
}
// 创建子组件
const Child1 = (props)=>{
return (
<p>计数:{props.data}</p>
)
}
const Child2 = (props)=>{
return (
<button onClick={()=>props.sendData()}>点击+1</button>
)
}
// 将父组件暴露出去
export default Counter
4. Context
// 导入react
import React from "react";
// 创建 Provider(提供数据) 和 Consumer(消费数据) 两个组件
const { Provider, Consumer } = React.createContext();
// 创建组件
class App extends React.Component{
render(){
return (
<Provider value={'我是傻逼'}>
<div>
<Node />
</div>
</Provider>
)
}
}
const Node =props => {
return (
<SubNode />
)
}
const SubNode = props => {
return (
<Child />
)
}
const Child = props => {
return (
<div>我是子节点
<Consumer>
{data=><h1>接收到的数据--{data}</h1>}
</Consumer>
</div>
)
}
// 将App暴露出去
export default App
5. props 深入
5.1 children 属性
// 导入react
import React from "react";
// 创建组件
class Hello extends React.Component{
render(){
return (
<div>
组件的子节点:{this.props.children}
{console.log(this.props.children)}
</div>
)
}
}
// 将组件暴露出去
export default Hello
// index文件渲染
// ReactDOM.render(<Change><h1>我是一个大傻逼</h1></Change>, document.querySelector('#root'))
5.2 props 校验
// 1. 导入react,react-dom 两个包
import React from 'react'
import ReactDOM from 'react-dom'
// 导入prop-types包
import PropTypes from 'prop-types'
// 导入css
import './index.css'
// 添加组件
function App(props){
return (
<div>{props.a}{props.fn()}{props.tag}{props.fiter.area}</div>
)
}
// 约定属性类型
// 添加props校验
// 属性 a 的类型: 数值(number)
// 属性 fn 的类型: 函数(func) 并且为必填项
// 属性 tag 的类型: React元素(element)
// 属性 fiter 的类型: 对象(area:'上海', price: 1999)
App.propTypes = {
// 约定color属性为Arry
// 如果类型不对,则报出明确错误,便于分析错误原因
a: PropTypes.number,
fn: PropTypes.func.isRequired,
tag: PropTypes.element,
fiter: PropTypes.shape({
area: PropTypes.string,
price: PropTypes.number
})
}
// 渲染
ReactDOM.render(<App fn={()=><p>666</p>} a={11} tag={<h1>我是一个大傻逼</h1>} fiter={{area:'sdad',price:131232}}></App>, document.querySelector('#root'))
5.3 props 的默认值
6. 组件的生命周期
6.1 组件的生命周期概述
6.2 生命周期的三个阶段
1. 创建时( 挂载阶段 )
// 1. 导入react,react-dom 两个包
import React from 'react'
import ReactDOM from 'react-dom'
// 导入prop-types包
import PropTypes from 'prop-types'
// 导入css
import './index.css'
// 添加组件
class App extends React.Component{
constructor(){
super()
console.warn('挂载时:constructor');
}
// 1. 进行DOM操作
// 2. 发送ajax请求, 获取远程数据
componentDidMount(){
// axios.get('http://api.....')
const title = document.querySelector('#title');
console.log(title);
console.warn('挂载时:componentDidMount');
}
render(){
console.warn('挂载时:render');
return (
<div>
<h1 id="title">生命周期</h1>
</div>
)
}
}
// 添加props默认值
App.defaultProps={
pageSize:10
}
// 渲染
ReactDOM.render(<App></App>, document.querySelector('#root'))
2. 更新时(更新阶段)
// 1. 导入react,react-dom 两个包
import React from 'react'
import ReactDOM from 'react-dom'
// 导入prop-types包
import PropTypes from 'prop-types'
// 导入css
import './index.css'
// 添加组件
class App extends React.Component{
constructor(){
super()
}
state ={
count:0
}
// 状态加1
countAdd= ()=>{
this.setState({
count:this.state.count+1
})
// 演示强制更新
// this.forceUpdate()
}
render(){
console.warn('render');
return (
<div>
<Count count={this.state.count}></Count>
<button onClick={this.countAdd}>点击</button>
</div>
)
}
}
// 子组件
class Count extends React.Component{
render(){
console.warn('count-render');
return (
<h1 id='count'>计数:{this.props.count}</h1>
)
}
// 注意:如果要调用 setState() 更新状态,必须放在一个 if 条件中
// 因为:如果直接调用 setState() 更新状态,也会导致递归更新!!!
componentDidUpdate(prevProps){
const h = document.getElementById('count')
console.log(h);
// 错误演示!!!
// this.setState({})
// 正确做法:
// 做法: 比较更新前后的props是否相同,来决定是否重新渲染组件
console.log('上一次的prevProps:',prevProps,'当前的prevProps:',this.props);
if(prevProps.count!==this.props.count){
this.setState({
})
}
}
}
// 渲染
ReactDOM.render(<App></App>, document.querySelector('#root'))
3. 卸载时(卸载阶段)
// 1. 导入react,react-dom 两个包
import React from 'react'
import ReactDOM from 'react-dom'
// 导入prop-types包
import PropTypes, { func } from 'prop-types'
// 导入css
import './index.css'
// 添加组件
class App extends React.Component{
constructor(){
super()
}
state ={
count:0
}
// 状态加1
countAdd= ()=>{
this.setState({
count:this.state.count+1
})
// 演示强制更新
// this.forceUpdate()
}
render(){
console.warn('render');
return (
<div>
{
this.state.count > 4
? (<h1>豆豆被打死了</h1>)
: (<Count count={this.state.count}></Count>)
}
<button onClick={this.countAdd}>点击</button>
</div>
)
}
}
// 子组件
class Count extends React.Component{
componentDidMount(){
// 开启定时器
this.timerId=setInterval(()=>{
console.log(111);
},1000)
}
render(){
console.warn('count-render');
return (
<h1 id='count'>计数:{this.props.count}</h1>
)
}
componentWillUnmount() {
console.log('生命周期钩子函数: componentWillUnmount');
// 清除定时器
clearInterval(this.timerId)
}
}
// 渲染
ReactDOM.render(<App></App>, document.querySelector('#root'))
6.3 不常用钩子函数介绍
7. render-props 和高阶组件
7.1 React 组件复用概述
7.2 render props 模式
// 导入react reactDOM包
import React from "react";
import ReactDOM from "react-dom";
// render proprs模式
// 导入图片
import img from "./image/submarine.webp";
// 创建Mouse组件
class Mouse extends React.Component {
state = {
// 鼠标位置
x: 0,
y: 0,
};
// 鼠标移动事件的处理程序
mouseListen = (e) => {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
componentDidMount() {
// 监听鼠标的移动
window.addEventListener("mousemove", this.mouseListen);
}
render() {
// return null
return this.props.render(this.state);
}
}
class App extends React.Component {
render() {
return (
<div>
<h1>render props 模式 </h1>
<Mouse
render={(mouse) => {
return (
<h1>
X:{mouse.x},Y:{mouse.y}
</h1>
);
}}
/>
{/* 猫捉老鼠 */}
<Mouse
render={(mouse) => {
return (
<img
src={img}
alt="小飞机"
style={{
position: "absolute",
width: 50,
height: 50,
left: mouse.x,
top: mouse.y,
}}
/>
);
}}
/>
</div>
);
}
}
// 渲染
ReactDOM.render(<App />, document.getElementById("root"));
// 导入react reactDOM包
import React from "react";
import ReactDOM from "react-dom";
// 导入属性校验的包
import PropTypes from "prop-types";
// render proprs模式
// 导入图片
import img from "./image/submarine.webp";
// 创建Mouse组件
class Mouse extends React.Component {
state = {
// 鼠标位置
x: 0,
y: 0,
};
// 鼠标移动事件的处理程序
mouseListen = (e) => {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
componentDidMount() {
// 监听鼠标的移动
window.addEventListener("mousemove", this.mouseListen);
}
// 推荐在组件卸载时,移除事件绑定
componentWillUnmount() {
window.removeEventListener("mousemove", this.mouseListen);
console.log(33);
}
render() {
// return null
return this.props.children(this.state);
}
}
// 属性校验
Mouse.propTypes = {
children: PropTypes.func.isRequired,
};
class App extends React.Component {
render() {
return (
<div>
<h1>render props 模式 </h1>
<Mouse>
{(mouse) => {
return (
<h1>
X:{mouse.x},Y:{mouse.y}
</h1>
);
}}
</Mouse>
{/* 猫捉老鼠 */}
<Mouse>
{(mouse) => {
return (
<img
src={img}
alt="小飞机"
style={{
position: "absolute",
width: 50,
height: 50,
left: mouse.x,
top: mouse.y,
}}
/>
);
}}
</Mouse>
</div>
);
}
}
// 渲染
ReactDOM.render(<App />, document.getElementById("root"));
7.3 高阶组件
设置displayName
// 导入react reactDOM包
import React from "react";
import ReactDOM from "react-dom";
// 导入属性校验的包
import PropTypes, { func } from "prop-types";
// 高阶组件 HOC
// 导入图片
import img from "./image/submarine.webp";
// 创建高阶组件
function withMouse(WrappedComponent) {
// 创建Mouse组件
class Mouse extends React.Component {
// 设置鼠标状态值
state = {
x: 0,
y: 0,
};
// 控制鼠标逻辑
componentDidMount() {
// 绑定事件
window.addEventListener("mousemove", this.mouseMove);
}
componentWillUnmount() {
// 清除事件
window.removeEventListener("mousemove", this.mouseMove);
}
// 鼠标事件
mouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
render() {
return <WrappedComponent {...this.state} {...this.props}></WrappedComponent>;
}
}
// 设置displayName
Mouse.displayName = `WithMouse${getDispalyName(WrappedComponent)}`;
// 将组件返回出去
return Mouse;
}
// 设置组件displayName 方法
function getDispalyName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || "Component";
}
// 用来测试的组件
const Position = (props) => {
return (
<h1>
X:{props.x},Y:{props.y}
</h1>
);
};
// 用来测试的组件二:猫捉老鼠
const MoveImg = (props) => {
return (
<img
src={img}
alt="小飞机"
style={{
position: "absolute",
width: 50,
height: 50,
left: props.x,
top: props.y,
}}
/>
);
};
// 获取增强后的组件
const MousePosition = withMouse(Position);
const MouseMoveImg = withMouse(MoveImg);
class App extends React.Component {
render() {
return (
<div>
<h1>render props 模式 </h1>
<MousePosition />
<MouseMoveImg />
</div>
);
}
}
// 渲染
ReactDOM.render(<App />, document.getElementById("root"));
传递 props