React的核心基础笔记
程序猿最烦两件事,第一件事是别人要他给自己的代码写文档,第二件呢?是别人的程序没有留下文档。小编今天给大家总结了一份文档,都是我在学习react的时候的一些心得体会,可能不够官方,都是用我自己的大白话进行说明的,有不足的地方希望大佬指正。
一、React介绍:
-
起源:
- React 起源于 Facebook 于2013年5月开源.是一个用于构建用户界面的 JavaScript 库, 与vue,angular并称前端三大框架,现在最新版本是18
-
阐述:
- 它只提供 UI (view)层面的解决方案在实际的项目当中,它并不能解决我们所有的问题,需要结合其它的库,例如 Redux、React-router 等来协助提供完整的解决方法。
-
特点:
- 数据驱动
- 组件化
- 虚拟DOM
-
学习网站推荐:
- 英文官网: reactjs.org/
- 中文官网: zh-hans.reactjs.org/
- 官网文档:react.docschina.org
二、开发环境搭建
-
cdn引入js(不使用脚手架)
-
安装npm包
npm i react@17.0.0 react-dom@17.0.0 babel-standalone@6.26.0 //简单解释一下 react@17.0.0 // react核心 react-dom@17.0.0 //负责渲染 babel-standalone@6.26.0 // es6转es5 -
在html文档中引入
<script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.production.min.js"></script> <script src="./node_modules/babel-standalone/babel.js"></script> -
将 script 标签中的jsx内容转换为浏览器可以识别的 JavaScript
<script type="text/babel"></script>
-
-
使用脚手架工具创建项目
-
使用npm包管理工具
npx create-react-app my-app //创建一个react项目 cd my-app//去到项目文件夹 npm start//启动项目
-
三、React核心基础
-
helloReact(第一个react程序)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.production.min.js"></script> <script src="./node_modules/babel-standalone/babel.js"></script> </head> <body> <!-- 写一个根文件 --> <div id="root"></div> <!-- 蒋script的标签改为可识别 --> <script type="text/babel"> // ReactDOM.render(渲染的h2元素节点,渲染到root根节点去) ReactDOM.render(<h2>helloreact</h2>,document.getElementById('root')) </script> </body> </html> -
jsx语法:
-
概念:
- JSX 全称 JavaScript XML ,是一种扩展的 JavaScript 语言,它允许 HTML 语言直接写在 JavaScript 语言中,不加任何引号,这就是 JSX 语法。它允许 HTML 与 JavaScript 的混写。
-
语法规则:
- 必须只能有一个根节点
- *小括号()的内容当成html元素解析
- *插入js代码用大括号{}
- 单标签不能省略结束标签。/>
- JSX 允许直接在模板中插入一个 JavaScript 表达式
-
示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.production.min.js"></script> <script src="./node_modules/babel-standalone/babel.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> /* 多行的react元素,必须有根元素*/ // 定义变量 let message = '第一个react程序' let user = { name:'jack', age:18 } let list = ['我是数组1','我是数组2'] let person = { name:'我是一个对象' } // 定义元素 // 1、小括号()的内容当成html元素解析 // 2、插入js代码用大括号{} // 3、jsx就是javaScript XML,是一种扩展的js语言 // 它允许 HTML 语言直接写在 JavaScript 语言中,不加任何引号,这就是 JSX 语法。 // 它允许 HTML 与 JavaScript 的混写。 const element =( <div> <h2>{message}</h2> <p>姓名:{user.name}</p> <p>年龄:{user.age}</p> <p>数组:{list[0]}</p> <p>对象:{person.name}</p> </div> ) ReactDOM.render(element,document.getElementById('root')) </script> </body> </html> 网页显示效果如下 第一个react程序 姓名:jack 年龄:18 数组:我是数组1 对象:我是一个对象
-
-
操作元素
-
操作内容
-
操作属性
-
操作样式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.production.min.js"></script> <script src="./node_modules/babel-standalone/babel.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> let title = '操作内容' let url = 'https://www.baidu.com/' let sty = { color:'red', fontSize:'18px' } // 绑定点击事件函数 function bindClick(){ alert('我是绑定点击事件') } // 定义元素内容 const element = ( <div> <button onClick={bindClick}>我是一个绑定事件按钮</button> {/* 操作内容 */} <h2>{title}</h2> {/* 操作属性 */} <a href={url}>跳转百度</a> {/* 操作样式 */} <p style={sty}>操作样式变红</p> {/* 直接写一个对象操作样式 */} <p style={{color:'blue'}}>直接写一个样式变蓝</p> </div> ) ReactDOM.render(element,document.getElementById('root')) </script> </body> </html>
-
-
Fragments:
-
概念:Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。
-
简写:
<></> -
示例:
<React.Fragment> <h2>列表</h2> <ul> <li>元素一</li> <li>元素二</li> </ul> </React.Fragment>
-
-
列表渲染
-
概念:与vue里面的v-for比起来复杂点,这里使用的是map方法
-
-
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>helloworld</title> <script src="./js/react.development.js"></script> <script src="./js/react-dom.development.js"></script> <script src="./js/babel.js"></script> <style> ul, li { list-style: none; } .y-table { width: 80%; margin: 0 auto; } .y-table tr, td { border-bottom: 1px dotted gray; } </style> </head> <body> <div id="root"></div> <script type="text/babel"> let list = [ { id: 1001, name: 'javascript高级编程', price: 88.78 }, { id: 1002, name: 'vue高级编程', price: 188.58 }, { id: 1003, name: 'react高级编程', price: 288.59 }, ] const element = ( <div> <h2>列表渲染</h2> <ul> {list.map(item => ( <li> {item.id} - {item.name} - {item.price} </li> ))} </ul> <h2>列表渲染table表格</h2> <table className="y-table"> {list.map(item => ( <tr key={item.id}> <td>{item.id}</td> <td>{item.name}</td> <td>{item.price}</td> </tr> ))} </table> </div> ) ReactDOM.render(element, document.getElementById('root')) </script> </body> </html>
-
-
条件渲染:
-
概念:通过if语句、三元运算符、逻辑与或非运算符进行运算
-
-
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.production.min.js"></script> <script src="./node_modules/babel-standalone/babel.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> let age = 19 function getUser(flag){ if(flag == 0){ return <h2>我是在线的状态</h2> }else if(flag == 1){ return <h2>我是离线状态</h2> }else if(flag == 2){ return <h2>我是隐身的状态</h2> } } const element = ( <div> {/* 通过if语句进行条件判断 */} {getUser(0)} {getUser(1)} {getUser(2)} {/* 通过三元运算符 表达式?真:假 */} {age >18?<h2>成年人</h2>:<h2>未成年人</h2>} {/* 通过与或非表达式 */} {age > 18 && <h2>成年人</h2>} </div> ) ReactDOM.render(element,document.getElementById('root')) </script> </body> </html>
-
-
State组件内部数据
-
概念:state,叫做状态,是用来盛放数据的。
-
一般写法示例:
import React, { Component } from "react";
export default class App extends Component {
// 定义state的第一种方式
// 这种方式就是构造器的方式
constructor() {
super(); // 因为继承了父类 所以需要使用super 函数
this.state = {
num: 0,
uname: "zrs",
};
}
render() {
return (
<div>
{/* 使用状态 */}
{this.state.num}-{this.state.uname}
</div>
);
}
}
-
简写示例
import React, { Component } from "react"; export default class App extends Component { // 定义状态的第二种方式 state = { num: 0, uname: "zrs", }; render() { return ( <div> {/* 使用方式没有任何变化 */} {this.state.num}-{this.state.uname} </div> ); } }
-
事件
-
注意事项:
- 在点击事件函数中的this,指向的是undefined
- 在构造器里面改变点击事件函数的this指向,将它从新指向为事件源
- 使用箭头函数this指向是上下文的特殊性,来改变this指向
-
绑定事件写法一
-
直接在大括号里面写一个箭头函数、在函数中直接书写逻辑代码;缺点:逻辑代码写太多维护起来就会很复杂
import React, { Component } from "react";
export default class App extends Component {
state = {
uname: "zrs",
};
render() {
return (
<div>
<button
onClick={() => {
let uname = "zzr";
// 这里的 this 指向的是 实例对象
console.log("this:", this);
// 改变 state 的值 请使用 setState() 这个函数在修改值之后,才能触发render函数重新执行
this.setState({
uname,
});
}}
>
change
</button>
<div>{this.state.uname}</div>
</div>
);
}
}
-
绑定事件的写法二(需要修正this)
import React, { Component } from "react";
export default class App extends Component {
state = {
uname: "zrs",
};
// 将事件处理函数写在 外面 但是这种写法会有一个问题 就是需要修正this ,如果不修正this,this指向的是undefined
// 这个不是react留的坑,是js的坑,详情自行搜索
changeUname() {
let uname = "zzr";
console.log("this:", this);
this.setState({
uname,
});
}
render() {
return (
<div>
{/* 使用bind 函数修正 this */}
<button onClick={this.changeUname.bind(this)}>change</button>
<div>{this.state.uname}</div>
</div>
);
}
}
-
在构造器中修正this
import React, { Component } from "react"; export default class App extends Component { constructor(){ super() // 在构造器中修正this this.changeUname=this.changeUname.bind(this) } state = { uname: "zrs", }; changeUname() { let uname = "zzr"; console.log("this:", this); this.setState({ uname, }); } render() { return ( <div> <button onClick={ this.changeUname }>change</button> <div>{this.state.uname}</div> </div> ); } } -
绑定事件的写法三(箭头函数)
import React, { Component } from "react"; export default class App extends Component { state = { uname: "zrs", }; // 在这里写成箭头函数即可,因为箭头函数的this指向的是应用上下文 changeUname = () => { let uname = "zzr"; console.log("this:", this); this.setState({ uname, }); }; render() { return ( <div> <button onClick={this.changeUname}>change</button> <div>{this.state.uname}</div> </div> ); } } -
绑定事件的写法四
import React, { Component } from "react"; export default class App extends Component { state = { uname: "zrs", }; changeUname = () => { let uname = "zzr"; console.log("this:", this); this.setState({ uname, }); }; render() { return ( <div> {/* 第四种写法:给事件一个处理函数,在处理函数中调用处理逻辑的函数 所以这里添加了小括号 */} <button onClick={() => {this.changeUname()}} > change </button> <div>{this.state.uname}</div> </div> ); } }
-
事件对象和默认行为
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>事件对象与事件默认行为</title> <script src="./js/react.development.js"></script> <script src="./js/react-dom.development.js"></script> <script src="./js/babel.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> class Counter extends React.Component{ state = { url:'http://www.baidu.com' } render(){ return ( <div> <button onClick={ (e)=>{this.bindClick(e,this.state.url)} }>确定</button> <a href={this.state.url} onClick={this.bindBaidu}>百度</a> </div> ) } bindClick = (e,url)=>{ console.log('触发点击事件 事件对象event : ',url, e); } bindBaidu = (e)=>{ e.preventDefault() console.log('触发事件'); } } ReactDOM.render(<Counter/>, document.getElementById('root')) </script> </body> </html>
四、组件之间的通信
-
父传子
-
概念:在使用子组件的时候,在子组件上自定义一个属性,然后把父组件里面的值作为属性值传给子组件,然后子组件使用props接受
-
父组件代码
import React, { Component } from "react";
import Son from "./son";//引入子组件
export default class 我是父组件 extends Component {
state = {
// 这是父元素里面的参数
msg: "我是父传子的参数123",
};
render() {
return (
<div>
<h2>我是父组件</h2>
{/* 自定义一个属性,把父组件的值传入进去 */}
<Son info={this.state.msg}/>
</div>
);
}
}
-
子组件代码
import React, { Component } from 'react'
export default class 我是子组件 extends Component {
render() {
return (
<div>
<h4>我是子组件</h4>
<h4>{this.props.info}</h4>
</div>
)
}
}
-
父传子视图
-
-
子传父
-
概念:子传父就是在使用子组件的时候,将函数传给子组件,子组件触发该函数,修改父组件中的值
-
子组件
import React, { Component } from 'react'
export default class son1 extends Component {
state={
sonMsg:'我是子组件信息' //子组件的信息
}
render() {
return (
<div className='son'>
<h3>我是子组件</h3>
<button
//定义一个点击事件,调用props里面的callback
// 然后将子组件的参数,作为实参传入给callback这个函数
onClick={()=>{
this.props.callback(this.state.sonMsg)
}}
>子传父按钮</button>
</div>
)
}
}
- 父组件
import React, { Component } from 'react'
import Son1 from './son1'//引入子组件
import './ftos.css' //引入样式
export default class father1 extends Component {
state={
fatherMsg:'我是父组件原本信息'
}
render() {
return (
<div className='father'>
<h2>我是父组件</h2>
<h3>{this.state.fatherMsg}</h3>
<Son1
callback={(msg)=>{
this.getMssage(msg)
}}
/>
</div>
)
}
// msg作为形参,然后setState给faterMsg
getMssage=(msg)=>{
this.setState({fatherMsg:msg})
}
}
- 子传父图示
-
-
兄弟组件传值
-
概念:就是兄弟组件通过同一个父组件,一个子组件负责传值,另一个子组件负责接受参数
-
父组件代码
import React, { Component } from 'react'
import Son1 from './son1'
import Son2 from './son2'
import './btob.css'
export default class father extends Component {
state={
fatherMsg:''
}
render() {
return (
<div className='father'>
<h1>我是两个子组件的父组件</h1>
<p>{this.state.fatherMsg}</p>
<Son1 callback={(msg)=>{this.getMessage(msg)}}/>
<Son2 info={this.state.fatherMsg}/>
</div>
)
}
getMessage = (msg)=>{
this.setState({fatherMsg:msg})
}
}
- 子组件传值
import React, { Component } from "react";
export default class extends Component {
state = {
sendMsg: "我是子组件发送信息",
};
render() {
return (
<div className="son1">
<h2>我是子组件发送者11</h2>
<button
onClick={() => {
this.props.callback(this.state.sendMsg);
}}
>
点击发送son1组件信息
</button>
</div>
);
}
}
- 子组件接受值
import React, { Component } from 'react'
export default class
extends Component {
render() {
return (
<div className='son2'>
<h2>我是子组件接收者</h2>
<p>{this.props.info}</p>
</div>
)
}
}
-
兄弟组件传参图示
-
-
提供者和消费者
-
提供者与消费者可用来实现跨级通信,提供者
provider提供数据,消费者consumer使用数据。需要注意的是provider有一个固定的属性value,consumer需要使用函数然后返回jsx的形式,这样设计便于传参。 -
提供者
import React, { Component } from "react";
import Consumer1 from "./Consumer";
// 创建一个 context 对象
export const { Provider, Consumer } = React.createContext();
export default class App extends Component {
state = {
info: "父组件的信息",
};
render() {
return (
<Provider
// value 是固定的写法
value={{
uname: "这里是父组件传递给子组件的",
info: this.state.info,
changInfo: (info1) => {
this.setState({ info: info1 });
},
}}
>
<div>父组件</div>
<Consumer1 />
</Provider>
);
}
}
- 消费者
import React, { Component } from "react";
// 这里引入的消费者 对象 必须是和 提供者配对的
import { Consumer } from "./Provider";
export default class Son extends Component {
render() {
return (
<Consumer>
{/* // 这里的value 就是提供者的那个value里面的值 */}
{(value) => (
<div>
子组件 {value.uname}---{value.info}
<button
onClick={() => {
value.changInfo("12312314323454");
}}
>
change
</button>
</div>
)}
</Consumer>
);
}
}
-
ref操作节点
-
概念:通过在元素中绑定ref,来操作节点
-
示例
-
父组件
import React, { Component } from 'react' import Son from './Son' export default class father extends Component { myrefH2 = React.createRef() // myrefSon = React.createRef() render() { return ( <div> {/* ref可以绑定标签元素 */} <h2 ref={this.myrefH2}>我是一个h2标签</h2> <button onClick={()=>{ console.log(this.myrefH2); console.log(this.myrefH2.current); }}>查看myrefH2按钮</button> <Son ref={this.myrefSon}/> <button onClick={()=>{ console.log(this.myrefSon); console.log(this.myrefSon.current); console.log(this.myrefSon.current.state); }}>查看myrefSon按钮</button> </div> ) } } -
子组件
import React, { Component } from 'react' export default class Son extends Component { state={ msg:'我是子组件的state数据' } render() { return ( <div> <h3>我是子组件</h3> </div> ) } } -
图示
-
五、react生命周期
- 概念:
- React生命周期指 React组件实例从创建运行到销毁经历的一系列过程。
- 注意react的函数式组件没有生命周期函数这一说,函数式组件要实现生命周期的功能,需要在副作用函数中实现。下面介绍的是类组件的生命周期函数。
-
三种执行阶段
-
初始化阶段
-
- 先执行 `constructor` 函数 =》然后是 `render` 函数 =》然后是 `componentDidMount` 函数。
/**
* 这个函数会在render函数执行之后立即执行,
* 1. 这时这个函数中可以执行一些关于dom的操作
* 2. 也可以做一些请求后端数据的工作
* 3. 也可以做一些定时器之类的活
*/
componentDidMount() {
console.log("初始化阶段的最后一个执行函数");
}
-
运行阶段
- 先执行render函数=》然后就是`componentDidUpdate `函数
/**
* 该函数有三个参数
* 第一个参数是之前的属性
* 第二个参数是之前的状态
*
* 在这个函数中做一些操作,都需要在判断条件中执行,不然很容易造成死循环
*/
componentDidUpdate(prevProps, prevState) {
console.log(prevProps, prevState);
console.log("更新阶段");
}
-
销毁阶段
- 直接
componentWillUnmount函数在,这个生命周期函数中做的事: 1. 清除定时器 2. 解绑dom事件
- 直接
// 这个函数在组件销毁的时候执行
componentWillUnmount() {
console.log("组件销毁了");
}
-
完整的总代码演示
- 父组件
import React, { Component } from "react";
import Demo from "./Demo";
export default class App extends Component {
state = {
flag: true,
};
render() {
return (
<div>
<h2>App</h2>
{this.state.flag && <Demo />}
<button
onClick={() => {
let flag = this.state.flag;
flag = !flag;
this.setState({ flag });
}}
>
显示/隐藏子组件
</button>
</div>
);
}
}
2. 子组件
import React, { Component } from "react";
export default class Demo extends Component {
constructor() {
super();
this.state = {
num: 0,
};
}
render() {
return (
<div>
Demo
<h2>{this.state.num}</h2>
<button
onClick={() => {
let num = this.state.num;
num++;
this.setState({ num });
}}
>
chang
</button>
</div>
);
}
/**
* 这个函数会在render函数执行之后立即执行,这个函数只会执行一次
* 1. 这时这个函数中可以执行一些关于dom的操作
* 2. 也可以做一些请求后端数据的工作
* 3. 也可以做一些定时器之类的活
*/
componentDidMount() {
console.log("初始化阶段的最后一个执行函数");
}
/**
* 该函数有三个参数
* 第一个参数是之前的属性
* 第二个参数是之前的状态
*
* 在这个函数中做一些操作,都需要在判断条件中执行,不然很容易造成死循环
*/
componentDidUpdate() {
console.log("更新阶段");
}
// 这个函数在组件销毁的时候执行,这个函数只会执行一次
componentWillUnmount() {
console.log("组件销毁了");
}
}
-
在生命周期中创建和销毁一个定时器
- 父组件
import React, { Component } from 'react'
import Date from './Date'
export default class Myapp extends Component {
state={
flag:false
}
render() {
return (
<div>
<h2>我是app主页</h2>
{/* 设置一个点击事件,对state状态值进行管理 */}
<button onClick={this.undate}>隐藏或显示组件</button>
{/* 如果为真就显示组件、如果为假就不显示组件 */}
{this.state.flag?<Date/>:null}
</div>
)
}
undate= ()=>{
let flag = this.state.flag
flag = !flag
this.setState({flag})
if(flag){
alert('已经显示组件')
}
}
}
2. 子组件
import React, { Component } from 'react'
export default class Clock extends Component {
state = {
date: new Date(),
}
render() {
return (
<div>
<h2>电子时钟</h2>
{this.state.date.toLocaleTimeString()}
</div>
)
}
componentDidMount() {
this.timer()// 在挂载的时候调用,定时器
console.log('完成挂载');
}
componentDidUpdate() {
console.log('完成更新')
}
// 定时器
timer() {
this.intervalTimer = setInterval(() => {
this.setState({ date: new Date() })
}, 1000)
}
componentWillUnmount() {
console.log('Clock componentWillUnmount')
clearInterval(this.intervalTimer) //清除定时器
}
}
六、函数式组件-hook
-
hook简介:
- Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。
- Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React, Hook 是 React 16.8 的新增特性。
- 常用Hook: useState() useEffect() useRef() useContext()
-
hook特点:
- 在组件之间复用状态逻辑, 无需修改组件结构
- 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),而并非强制按照生命周期划分
- 不编写 class 的情况下使用 state 以及其他的 React 特性
-
使用state Hook:
- 在函数组件里没有this指向的问题,直接调用
- useState会返回一对值,当前状态和更新状态。还有初始值
import React,{useState} from 'react'
export default function Testhook() {
// [参数,设置参数] = useState(参数的初始值)
const [num,setNum] = useState(0)
// [参数,设置参数] = useState(参数的初始值)
const [msg,setMsg] = useState('初始值')
return (
<div>
{/* 在函数组件里面没有this指向问题,直接调用定义好的参数 */}
<h2>直接使用num数值</h2>
<h3>{num}</h3>
{/* 点击更改设置好的参数 */}
<button onClick={()=>{
setNum(num+1)
}}>点击num加一</button>
<h2>直接使用msg字符串</h2>
<h3>{msg}</h3>
<button onClick={()=>{
setMsg('已经更改msg信息')
}}>点击更改msg信息</button>
</div>
)
}
-
Effect Hook(副作用)
-
函数组件主要作用是通过数据渲染UI界面,除了这个之外的操作就是副作用。
-
ajax请求
-
手动修改dom
-
localstorage操作
-
-
执行的时机
- 默认状态=>首次执行、每次组件更新
- 添加空[ ]=>首次执行
- 添加依赖项[count]=>首次执行、依赖项发生变化
-
普通的副作用
js
import React,{useState,useEffect}from 'react'
export default function Fzy() {
const [num,setNum] = useState(0)
const [msg,setMsg] = useState('初始值')
useEffect(()=>{
console.log('副作用只有一个参数的时候,在初始化和组件刷新的时候调用');
})
useEffect(()=>{
console.log('副作用第二参数是一个空数组的时候,只有初始化的时候调用');
},[])
useEffect(()=>{
console.log('副作用第二参数有值的时候,初始化和只要数组里面的值变化,就触发函数');
},[num])
return (
<div>
<h2>查看num的值</h2>
<p>{num}</p>
<button onClick={()=>{
setNum(num+1)
}}>点击加一</button>
</div>
)
}
- 利用副作用清除定时器
- 父组件
import React, { Component } from 'react'
// import Date from './Date'
import HookDate from './HookDate'
export default class Myapp extends Component {
state={
flag:false
}
render() {
return (
<div>
<h2>我是app主页</h2>
{/* 设置一个点击事件,对state状态值进行管理 */}
<button onClick={this.undate}>隐藏或显示组件</button>
{/* 如果为真就显示组件、如果为假就不显示组件 */}
{this.state.flag?<HookDate/>:null}
</div>
)
}
undate= ()=>{
let flag = this.state.flag
flag = !flag
this.setState({flag})
if(flag){
alert('已经显示组件')
}
}
}
2. 子组件
import React,{useState,useEffect} from 'react'//导入方法
export default function HookDate() {
const [date,setDate] =useState('')
useEffect(()=>{
// 定义一个计时器
let interValTimer = setInterval(()=>{
let time = new Date().toLocaleTimeString()
setDate(time)//将获取到的值设置给date
},1000)
// 清理副作用方法
return ()=>{
console.log('清理副作用');
clearInterval(interValTimer)
}
},[])
return (
<div>
<h2>我是子组件时钟</h2>
{date}
</div>
)
}
-
hook之间的提供者和消费者传参
- 提供者
import React from "react";
// 引入子组件
import Demo from "./Son";
// 创建一个 context 对象 导出一下,
// 因为子组件需要使用这个对象中的一个消费者对象
export const GlobalContext = React.createContext();
export default function App() {
return (
<GlobalContext.Provider
value={{
val: "我是来自父组件的传值",
num: 1234,
}}
>
<h2>我是父组件</h2>
<Demo />
</GlobalContext.Provider>
);
}
1. 消费者
import React, { useContext } from "react";
// 引入导出的那个 context 对象
import { GlobalContext } from "./Father";
export default function ComC() {
// 使用 useContext 的使用 将导入的 context 对象作为参数传入
// 这个函数会返回 提供者的 value属性的值
const text = useContext(GlobalContext);
return (
<div>
<h3>我是子组件</h3>
<p>接受父组件val:{text.val}</p>
<p>接受父组件num:{text.num}</p>
</div>
);
}
- 自定义hook
- 自定义hook文件(必须是use开头)
import { useState } from "react";
// 这个函数就是自定义的 hook
export function useScrollTop() {
// 还是定义一个useState
const [height, setheight] = useState(0);
// 只要检测到左边滑轮就设置一次setheight
window.addEventListener("scroll", () => {
let h = document.documentElement.scrollTop;
setheight(h);
});
// 把获取到的值返回
return [height];
}
2. 引入我的自定义hook
import React, { useContext,useState } from "react";
// 引入自定义hook
import {useScrollTop} from './useScrollTop'
import './my.css'//引入一个高度样式height10000
export default function ComC() {
// 使用引入的useScrollTop
const [scrollTop,setscrollTop] = useScrollTop(0)
return (
<div className="h">
<p>{scrollTop}</p>
</div>
);
}