/*
函数组件
1.函数名称开头字母要大写, 在使用组件时是直接把函数名当做标签
2.要有return返回值, 如果没有组件内容return null
*/
function Hello() {
return (
<p>这是第一个函数组件</p>
)
}
//2. 将组件渲染到页面上
ReactDOM.render(<Hello/>, document.getElementById('rootReact'))
// ReactDOM.render函数执行的过程
// 1.React 解析组件标签MyComponent, 找到了组件MyComponent
// 2.发现这个组件是使用函数自定义的,执行这个函数,随后将返回的虚拟DOM转成真是DOM,呈现到屏幕上
/*
类组件
1.使用ES6的类class创建组件
2.类名的首字母为大写
3.类需要继承自React.Component
4.必须要实现render方法,在render方法中通过return返回值或者return null
*/
class World extends React.Component {
render() {
return (
<div>
<p>这是第一个类组件</p>
</div>
)
}
}
ReactDOM.render(<World/>, document.getElementById('rootReact'))
// ReactDOM.render函数执行的过程
// 1.React 解析组件标签MyClassComponent, 找到了组件MyClassComponent
// 2.发现这个组件是类自定义组件,就new出这个类的实例对象,然后调用实例对象的render方法
// 3.随后将返回的虚拟DOM转成真是DOM,呈现到屏幕上
类组件的两大特性:变量state与生命周期。
import React from "react";
class HelloWorld extends React.Component {
render() {
return (
<div>
这是第一个文件抽离组件
</div>
)
}
}
export default HelloWorld
class MyBtn extends React.Component{
handleClick() {
console.log('按钮点击了')
}
render() {
return (
<button onClick={this.handleClick}>类组件按钮:点击我</button>
)
}
}
function MyBigBtn() {
function handleClick() {
console.log("函数按钮被点击了")
}
return (
<button onClick={handleClick}>函数组件按钮:点击我</button>
)
}
事件对象
function MyBigBtn() {
function handleClick(e) {
e.preventDefault()//阻止事件默认行为
console.log("函数按钮被点击了",e)
}
return (
<button onClick={handleClick}>函数组件按钮:点击我</button>
)
}
import React from "react";
class State extends React.Component{
//state初始化方式一
constructor() {
super();
this.state = {
count:0
}
}
//state初始化方式一
// state={
// count:0
// }
render() {
return (
<div>
计数值:{this.state.count}
</div>
);
}
}
export default State
render() {
return (
<div>
计数值:{this.state.count}
<button onClick={()=>{
this.setState({
count: this.state.count+1
})
}}>+1</button>
</div>
);
}
class State extends React.Component{
incrementCount() {
//this为undefined
this.setState({
count: this.state.count+1
})
}
render() {
return (
<div>
计数值:{this.state.count}
<button onClick={this.incrementCount}>+1</button>
</div>
);
}
}
{/*<button onClick={this.incrementCount}>+1</button>*/}
<button onClick={()=>this.incrementCount()}>+1</button>
class State extends React.Component{
//state初始化方式一
constructor() {
super();
this.state = {
count:0
}
this.incrementCount = this.incrementCount.bind(this)
}
incrementCount() {
//this为undefined
this.setState({
count: this.state.count+1
})
}
incrementCount = () => {
//this为undefined
this.setState({
count: this.state.count+1
})
}
render() {
return (
<div>
计数值:{this.state.count}
<button onClick={this.incrementCount}>+1</button>
</div>
);
class Form extends React.Component{
state={
txt: ""
}
handleTextChange = (e) => {
this.setState({
txt: e.target.value
})
}
render() {
return (
<div>
<input type={"text"} value={this.state.txt} onChange={this.handleTextChange}/>
</div>
);
}
}
import React from "react";
class Form extends React.Component{
state={
txt: "",
content:"",
selectV:"sh",
isChecked:true
}
handleTextChange = (e) => {
this.setState({
txt: e.target.value
})
}
handleContent = e => {
this.setState({
content: e.target.value
})
}
handleSelectV = e => {
this.setState({
selectV: e.target.value
})
}
handleChecked = e => {
this.setState({
isChecked: e.target.isChecked
})
}
render() {
return (
<div>
<input type={"text"} value={this.state.txt} onChange={this.handleTextChange}/>
<textarea value={this.state.content} onChange={this.handleContent}></textarea>
<select value={this.state.selectV} onChange={this.handleSelectV}>
<option value="sh">上海</option>
<option value="bj">北京</option>
<option value="gz">广州</option>
</select>
<input type="checkbox" checked={this.state.isChecked} onChange={this.handleChecked}/>
</div>
);
}
}
handleChange = (e) => {
// 获取标签的值
const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value
// 获取标签的name属性
const name = e.target.name
// 更新动态属性的状态
this.setState({
[name]: value
})
}
render() {
return (
<div>
{/* 使用动态name属性更新 */}
<input name="txt" type={"text"} value={this.state.txt} onChange={this.handleChange}/>
<textarea name="content" value={this.state.content} onChange={this.handleChange}></textarea>
<select name="selectV" value={this.state.selectV} onChange={this.handleChange}>
<option value="sh">上海</option>
<option value="bj">北京</option>
<option value="gz">广州</option>
</select>
<input name="checkName" type="checkbox" checked={this.state.checkName} onChange={this.handleChange}/>
</div>
);
}
class Form extends React.Component{
constructor() {
super();
this.txtRef = React.createRef()
}
handleClick = () => {
console.log(this.txtRef.current.value)
}
render() {
return (
<div>
<input type={"text"} ref={this.txtRef}/>
<button onClick={this.handleClick}>获取非受控组件上的值</button>
</div>
);
}
ReactDom.render(<PropsTest name={"jack"} age={30} />, document.getElementById("root"))
//类组件接收参数
class PropsTest extends React.Component{
render() {
let {name, age} = this.props
return (
<div>
类组件名字: {name}
<br/>
类组件年龄: {age}
</div>
);
}
}
//函数组件接收参数
function PropsTest(props) {
return (
<div>
函数组件名字: {props.name}
<br/>
函数组件年龄: {props.age}
</div>
)
}
//1.任意类型传参
ReactDom.render(
<PropsTest name={"jack"}
age={30}
fn={()=>console.log("这是一个函数")}
list={["red","blue","green"]}/>,
document.getElementById("root"))
class PropsTest extends React.Component{
//构造函数调用super(props)
constructor(props) {
super(props);
console.log(props)
}
render() {
// 2.props中的属性不能修改
// this.props.name = "lucy"
console.log(this.props)
let {name, age} = this.props
return (
<div>
类组件名字: {name}
<br/>
类组件年龄: {age}
</div>
);
}
}
class Parent extends React.Component{
constructor(props) {
super(props);
}
render() {
let {name, age} = this.props
return (
<div>
<Child lastName={"王"}/>
</div>
);
}
}
function Child(props) {
return (
<div>
子组件:{props.lastName}
</div>
)
}
class Parent extends React.Component{
getChildMsg= (data) => {
console.log("接收到子组件数据:",data)
}
render() {
return (
<div>
父组件:
<Child tap={this.getChildMsg}/>
</div>
);
}
}
function Child(props) {
function handleClick() {
props.tap("刷抖音")
}
return (
<div>
子组件:{props.lastName}
<button onClick={handleClick}>点击我,传递消息到父组件</button>
</div>
)
}
//父组件
class Parent extends React.Component{
state={
tag: ''
}
handleChange = (data) => {
this.setState({
tag: this.state.tag + " " + data
})
}
render() {
return (
<div>
父组件:
<Child lastName={this.state.tag}/>
<ChildB changeAction={this.handleChange}/>
</div>
);
}
}
//子组件A
function Child(props) {
return (
<div>
子组件:{props.lastName}
</div>
)
}
//子组件B
function ChildB(props) {
return (
<div>
<button onClick={()=>{props.changeAction("B")}}>传递子组件B的B到A组件中去</button>
</div>
)
}
import React from "react";
const {Provider, Consumer} = React.createContext()
class Parent extends React.Component{
render() {
return (
<Provider value={"pink"}>
<div>
父组件:
<Child lastName={this.state.tag} tap={this.getChildMsg}/>
<ChildB changeAction={this.handleChange}/>
</div>
</Provider>
);
}
}
function ChildBB(props) {
return (
<div>
这是B组件的子组件,BB组件
<Consumer>
{data => <div>通过context跨层传递的值为: {data}</div>}
</Consumer>
</div>
)
}
function ChildA() {
return (
<div>
子组件A
<ChildAA>
<button>ChildAA标签的子组件</button>
</ChildAA>
</div>
)
}
const ChildAA = (props) => {
console.log(props.children)
return (
<div>
{props.children}
子组件AA
<Consumer>
{data => <div>根节点跨层传递数据{data}</div>}
</Consumer>
</div>
)
}
//1.在项目目录下安装类型约束工具prop-types
npm i prop-types
//2.导入类型约束工具
import PropTypes from "prop-types"
//3.为一个组件设置类型约束
ChildAA.propTypes = {
colors: PropTypes.array
}
PropTypes常用的约束类型和默认值
ChildAA.propTypes = {
colors: PropTypes.array,
fn: PropTypes.func,
age: PropTypes.number.isRequired,
ele: PropTypes.element,
person: PropTypes.shape({
title: PropTypes.string,
age: PropTypes.number
})
}
ChildAA.defaultProps = {
age: 10,
colors: ['red', 'blue', 'green']
}
class LifeCircle extends React.Component{
constructor() {
super();
console.warn("生命周期-挂载阶段-1:constructor")
}
componentDidMount() {
//componentDidMount执行时,DOM页面已经渲染完成,可以进行dom操作了
//是操作DOM,发送网络请求的地方
const title = document.getElementById("title")
console.warn("生命周期-挂载阶段-3:componentDidMount", title)
}
render() {
//每次渲染都会调用(包括:挂载阶段,更新阶段)
//render中不可用调用setState,会循环调用, setState流程做了2件事,一是更新状态数据,二是更新UI调用render方法
console.warn("生命周期-挂载阶段-2:render")
return (
<div>
生命周期组件
<h2 id={"title"}>标题</h2>
</div>
);
}
}
class LifeCircle extends React.Component{
handleClick = () => {
// this.setState({
// count: this.state.count + 1
// })
this.forceUpdate()
}
render() {
return (
<div>
生命周期组件
<Counter count={this.state.count}/>
<h2 id={"title"}>标题</h2>
<button onClick={this.handleClick}>点击更新</button>
</div>
);
}
}
//组件更新调用方法
class Counter extends React.Component{
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("更新阶段:componentDidUpdate-2")
//此阶段一般用于Dom操作,网络发送,如果调用了this.setState必须加if判断
if (prevProps.count !== this.props.count) {
this.state({})
}
}
render() {
console.log("更新阶段:render-1")
return (
<div>
计数器: {this.props.count}
</div>
);
}
}
class Counter extends React.Component{
componentDidMount() {
this.timerId = setInterval(()=>{
console.log("定时器打印了...")
}, 1000)
}
componentWillUnmount() {
console.log("组件要被卸载了:componentWillUnmount")
clearInterval(this.timerId)
}
render() {
console.log("更新阶段:render-1")
return (
<div>
豆豆被打了: {this.props.count} 次
</div>
);
}
}


<Mouse>
{}
</Mouse>
class ReUseComponent extends React.Component{
render() {
return (
<div>
父组件
//外部设置要展示的子组件内容
<Mouse render={(mouse) => {
return <p>当前坐标为:{mouse.x}, {mouse.y}</p>
}}/>
//猫捉老鼠
<Mouse render={(mouse) => {
return (
<img src={'./img/cat.jpeg'}
style={{position: "absolute", top:mouse.y,left:mouse.x}}/>
)
}}/>
</div>
);
}
}
class Mouse extends React.Component{
state = {
x: 0,
y: 0
}
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
componentDidMount() {
window.addEventListener("mousedown", this.handleMouseMove)
}
render() {
//2.将state传递到外部
//3.使用props.render的返回值作为要展示的内容
return this.props.render(this.state);
}
}
children子元素方式实现
class ReUseComponent extends React.Component{
render() {
return (
<div>
父组件
<Mouse>
{(mouse) => {
return <p>当前坐标为:{mouse.x}, {mouse.y}</p>
}}
</Mouse>
</div>
);
}
}
class Mouse extends React.Component{
state = {
x: 0,
y: 0
}
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
componentDidMount() {
window.addEventListener("mousedown", this.handleMouseMove)
}
render() {
return this.props.children(this.state);
}
}
class Mouse extends React.Component{
componentDidMount() {
window.addEventListener("mousedown", this.handleMouseMove)
}
componentWillUnmount() {
window.removeEventListener("mousedown", this.handleMouseMove)
}
render() {
return this.props.children(this.state);
}
}
Mouse.propTypes = {
children: PropTypes.func.isRequired
}
function withMouse(WrappedComponent) {
class Mouse extends React.Component{
state = {
x: 0,
y: 0
}
componentDidMount() {
window.addEventListener("mousemove", this.handleMouseMove)
}
componentWillUnmount() {
window.removeEventListener("mousemove", this.handleMouseMove)
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render() {
return (
<WrappedComponent {...this.state}/>
);
}
}
return Mouse
}
class PurePosition extends React.Component{
render() {
return (
<div>
高阶组件坐标位置:{this.props.x}, {this.props.y}
</div>
);
}
}
const MouseP = withMouse(PurePosition)
<MouseP />
return Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || "Component"
}
function withMouse(WrappedComponent) {
class Mouse extends React.Component{
state = {
x: 0,
y: 0
}
componentDidMount() {
window.addEventListener("mousemove", this.handleMouseMove)
}
componentWillUnmount() {
window.removeEventListener("mousemove", this.handleMouseMove)
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render() {
return (
<WrappedComponent {...this.state} {...this.props}/>
);
}
}
return Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
}