import ReactDOM from 'react-dom/client';
// 创建一个react元素
const App=我是react-app
// 获取根元素
const root = ReactDOM.createRoot(document.getElementById('root'));
// 渲染元素
root.render(App);
function componentFun(props){
const {name,age} = props;
const onClick=()=>{
console.log('点击事件')
}
return 我是函数式组件{name}-{age}
}
* 类组件的props是存储到类的实例对象中,
* 可以直接通过实例对象访问
* this.props
* 类组件中state统一存储到了实例对象的state属性中
* 可以通过 this.state来访问
* 通过this.setState()对其进行修改
* 当我们通过this.setState()修改state时,
* React只会修改设置了的属性
import React, {Component} from 'react';
Class App extentds React.Component {
// 声明ref 绑定dom 用于直接操作dom
divRef = React.createRef();
state = {
count: 0,
test: '水电费啦',
}
// 为了省事,在类组件中响应函数都应该以箭头函数的形式定义
onClick = ()=>{
this.setState(prevState => {
return {
count: prevState + 1
}
});
/*this.setState({
obj:{...this.state.obj, name:'沙和尚'}
});*/
console.log("点我啊",this.divRef)
}
redner(){
return
我是一个类组件{this.props.name}-{this.props.age}
{this.state.count}-{this.state.test}
我是divRef
}
}
import React,{useState} from 'react'
const [formData,setFormData]=useState({
inputDesc:''
})
const onInputChange=(e)=>{
setFormData({
...formData,
inputTime: e.target.value
});
}
return
import ReactDOM from 'react-dom'
// 获取backdrop的根元素
const backdropRoot = document.getElementById('backdrop-root');
const Backdrop = (props) => {
// props.children 为插入的子节点 类似于vue的插槽
return ReactDOM.createPortal(
{props.children}
, backdropRoot);
};
const App = () => {
/*
* 它只会将它里边的子元素直接返回,不会创建任何多余的元素
* - 当我们希望有一个父容器
* 但同时又不希望父容器在网页中产生多余的结构时
* 就可以使用Fragment
* */
return (
<>
第一个组件
第二个组件
第三个组件
>
);
};
import React from 'react';
/*
* Context相当于一个公共的存储空间,
* 我们可以将多个组件中都需要访问的数据统一存储到一个Context中,
* 这样无需通过props逐层传递,即可使组件访问到这些数据
*
* 通过React.createContext()创建context
*
* */
const TestContext = React.createContext({
name:'孙悟空',
age:18
});
export default TestContext;
import TextContext from "./store/testContext"
const APP=()=>{
const [] = useState({
items: [],
totalAmount: 0,
totalPrice: 0,
})
return (
)
}
import React, {useContext} from 'react';
import TestContext from "../store/testContext";
* 当我们通过Context访问数据时,他会读取离他最近的Provider中的数据,
* 如果没有Provider,则读取Context中的默认数据
const B = () => {
// 使用钩子函数获取Context
const ctx = useContext(TestContext);
return (
{ctx.name} -- {ctx.age}
);
};
export default B;
4.子组件A中使用
import React from "react";
import TestContext from "../store/testContext";
* 使用 Xxx.Consumer 组件来创建元素
* Consumer 的标签体需要一个回调函数
* 它会将context设置为回调函数的参数,通过参数就可以访问到context中存储的数据
const A = () => {
return (
{(ctx) => {
return (
{ctx.name} - {ctx.age}
);
}}
);
};
export default A;
const App = () => {
const [count, setCount] = useState(0);
// setCount(0);
/*
* Too many re-renders.
* - 当我们直接在函数体中调用setState时,就会触发上述错误
* - 问题:
* 当新的state值和旧值相同时,它是不会触发组件的重新渲染的
* - setState()的执行流程(函数组件)
* setCount() --> dispatchSetDate()
* -->会先判断,组件当前处于什么阶段
* 如果是渲染阶段 --> 不会检查state值是否相同
* 如果不是渲染阶段 --> 会检查state的值是否相同
* - 如果值不相同,则对组件进行重新渲染
* - 如果值相同,则不对组件进行重新渲染
* 如果值相同,React在一些情况下会继续执行当前组件的渲染
* 但是这个渲染不会触发其子组件的渲染,这次渲染不会产生实际的效果
* 这种情况通常发生在值第一次相同时
*
* */
// useEffect()是一个钩子函数,需要一个函数作为参数,
// 这个作为参数的函数,将会在组件渲染完毕后执行
// 在开发中,可以将那些会产生副作用的代码编写到useEffect的回调函数中
// 这样就可以避免这些代码影响到组件的渲染
useEffect(() => {
setCount(1);
});
const clickHandler = () => {
console.log("点击按钮!");
setCount(1);
};
return (
{count}
);
};
/*
* 默认情况下,useEffect()中的函数,会在组件渲染完成后调用,
* 并且是每次渲染完成后都会调用
*
* 在useEffect()可以传递一个第二个参数,
* 第二个参数是一个数组,在数组中可以指定Effect的依赖项
* 指定后,只有当依赖发生变化时,Effect才会被触发
* 通常会将Effect中使用的所有的局部变量都设置为依赖项
* 这样一来可以确保这些值发生变化时,会触发Effect的执行
* 像setState()是由钩子函数useState()生成的
* useState()会确保组件的每次渲染都会获取到相同setState()对象
* 所以setState()方法可以不设置到依赖中
* 如果依赖项设置了一个空数组,则意味Effect只会在组件初始化时触发一次
* */
useEffect(()=>{
setCount(1);
},[count]);
// 引入
import React, { useReducer } from 'react';
// 定义cartReducer 一定要return
const cartReducer = (state, action)=>{
switch (action.type){
case 'ADD':
return {...state,count:state.count+action.count};
default:
return state;
}
};
const [cartData, cartDispatch] = useReducer(cartReducer, {
count:0
});
// 使用
cartDispatch({type:'ADD', count:5});
import React from 'react';
const B = (props) => {
return (
{props.test}--组件B
);
};
/*
* React.memo() 是一个高阶组件
* 它接收另一个组件作为参数,并且会返回一个包装过的新组件
* 包装过的新组件就会具有缓存功能,
* 包装过后,只有组件的props发生变化化
* 才会触发组件的重新的渲染,否则总是返回缓存中结果
* */
export default React.memo(B);
const App = () => {
const [count, setCount] = useState(1);
const [num, setNum] = useState(1);
/*
* useCallback()
* 参数:
* 1. 回调函数
* 2. 依赖数组
* - 当依赖数组中的变量发生变化时,回调函数才会重新创建
* - 如果不指定依赖数组,回调函数每次都会重新创建
* - 一定要将回调函数中使用到的所有变量都设置到依赖数组中
* 除了(setState)
* */
const clickHandler = useCallback(() => {
setCount(prevState => prevState + num);
setNum(prevState => num + 1);
}, [num]);
return (
);
};
1.使用createSlice 创建reducer的切片(新建一个store/index.js文件)
//使用RTK来构建store
import {configureStore, createSlice} from "@reduxjs/toolkit";
// createSlice 创建reducer的切片
// 它需要一个配置对象作为参数,通过对象的不同的属性来指定它的配置
const stuSlice = createSlice({
name:'stu', // 用来自动生成action中的type
initialState:{
name:'孙悟空',
age:18,
gender:'男',
address:'花果山'
}, // state的初始值
reducers:{ // 指定state的各种操作,直接在对象中添加方法
setName(state, action){
// 可以通过不同的方法来指定对state的不同操作
// 两个参数:state 这个state的是一个代理对象,可以直接修改
state.name = '猪八戒';
},
setAge(state, action){
state.age = 28;
}
}
});
// 切片对象会自动的帮助我们生成action
// actions中存储的是slice自动生成action创建器(函数),调用函数后会自动创建action对象
// action对象的结构 {type:name/函数名, payload:函数的参数}
export const {setName, setAge} = stuSlice.actions;
// const nameAction = setName('哈哈');
// const ageAction = setAge(30);
// console.log(nameAction);
// console.log(ageAction);
// 创建store 用来创建store对象,需要一个配置对象作为参数
const store = configureStore({
reducer:{
student:stuSlice.reducer
}
});
export default store;
2.在需要使用store顶级组件中暴露store
import ReactDOM from "react-dom/client";
import App from "./App";
import {Provider} from "react-redux";
import store from './store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
);
3.引入使用
import React from 'react';
import {useDispatch, useSelector} from "react-redux";
import {setName, setAge} from './store';
const App = () => {
// useSelector() 用来加载state中的数据
const student = useSelector(state => state.student);
// 通过useDispatch()来获取派发器对象
const dispatch = useDispatch();
// 获取action的构建器
const setNameHandler = () => {
dispatch(setName('沙和尚'));
};
const setAgeHandler = () => {
dispatch(setAge(33));
};
return (
{student.name} ---
{student.age} ---
{student.gender} ---
{student.address}
);
};
export default App;