/* 函数组件 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)}` }