React核心基础(上)

React的核心基础笔记

程序猿最烦两件事,第一件事是别人要他给自己的代码写文档,第二件呢?是别人的程序没有留下文档。小编今天给大家总结了一份文档,都是我在学习react的时候的一些心得体会,可能不够官方,都是用我自己的大白话进行说明的,有不足的地方希望大佬指正。
在这里插入图片描述

文章目录

  • React的核心基础笔记
    • 一、React介绍:
      • 起源:
      • 阐述:
      • 特点:
      • 学习网站推荐:
    • 二、开发环境搭建
      • cdn引入js(不使用脚手架)
      • 使用脚手架工具创建项目
    • 三、React核心基础
      • helloReact(第一个react程序)
      • jsx语法:
        • 概念:
        • 语法规则:
      • 操作元素
      • Fragments:
      • 列表渲染
      • 条件渲染:
      • State组件内部数据
      • 事件
        • 绑定事件的写法二(需要修正this)
        • 在构造器中修正this
        • 绑定事件的写法三(箭头函数)
        • 绑定事件的写法四
      • 事件对象和默认行为
    • 四、组件之间的通信
      • 父传子
        • 父组件代码
        • 子组件代码
      • 子传父
      • 兄弟组件传值
      • 提供者和消费者
      • ref操作节点
    • 五、react生命周期
      • 三种执行阶段
        • 初始化阶段
        • 运行阶段
        • 销毁阶段
      • 完整的总代码演示
      • 在生命周期中创建和销毁一个定时器
    • 六、函数式组件-hook
      • hook简介:
      • hook特点:
        • 使用state Hook:
        • Effect Hook(副作用)
        • 执行的时机
        • 普通的副作用
      • hook之间的提供者和消费者传参

一、React介绍:

  1. 起源:

    • React 起源于 Facebook 于2013年5月开源.是一个用于构建用户界面的 JavaScript 库, 与vue,angular并称前端三大框架,现在最新版本是18
  2. 阐述:

    • 它只提供 UI (view)层面的解决方案在实际的项目当中,它并不能解决我们所有的问题,需要结合其它的库,例如 Redux、React-router 等来协助提供完整的解决方法。
  3. 特点:

    • 数据驱动
    • 组件化
    • 虚拟DOM
  4. 学习网站推荐:

    • 英文官网: https://reactjs.org/
    • 中文官网: https://zh-hans.reactjs.org/
    • 官网文档:https://react.docschina.org

二、开发环境搭建

  1. cdn引入js(不使用脚手架)

    1. 安装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
      
    2. 在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>
      
    3. 将 script 标签中的jsx内容转换为浏览器可以识别的 JavaScript

      <script type="text/babel">script>
      
  2. 使用脚手架工具创建项目

    1. 使用npm包管理工具

      npx create-react-app my-app //创建一个react项目
      cd my-app//去到项目文件夹
      npm start//启动项目
      

三、React核心基础

  1. 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>Documenttitle><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">// ReactDOM.render(渲染的h2元素节点,渲染到root根节点去)ReactDOM.render(<h2>helloreact</h2>,document.getElementById('root'))script>
    body>
    html>
    
  2. jsx语法:

    • 概念:

      • JSX 全称 JavaScript XML ,是一种扩展的 JavaScript 语言,它允许 HTML 语言直接写在 JavaScript 语言中,不加任何引号,这就是 JSX 语法。它允许 HTML 与 JavaScript 的混写。
    • 语法规则:

      1. 必须只能有一个根节点
      2. *小括号()的内容当成html元素解析
      3. *插入js代码用大括号{}
      4. 单标签不能省略结束标签。/>
      5. 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对象:我是一个对象
      
  3. 操作元素

    在这里插入图片描述

    1. 操作内容

    2. 操作属性

    3. 操作样式

      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>Documenttitle><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>
      
  4. Fragments:

    • 概念:Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。

    • 简写:

      <>
      
    • 示例:

      <React.Fragment><h2>列表h2><ul><li>元素一li><li>元素二li>ul>
      React.Fragment>
      
  5. 列表渲染

    • 概念:与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>helloworldtitle><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>
      
  6. 条件渲染:

    • 概念:通过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 = 19function 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>
      
  7. 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>);}
    }
  1. 事件

  • 注意事项:

    1. 在点击事件函数中的this,指向的是undefined
    2. 在构造器里面改变点击事件函数的this指向,将它从新指向为事件源
    3. 使用箭头函数this指向是上下文的特殊性,来改变this指向
  • 绑定事件写法一

  • 直接在大括号里面写一个箭头函数、在函数中直接书写逻辑代码;缺点:逻辑代码写太多维护起来就会很复杂

import React, { Component } from "react";export default class App extends Component {state = {uname: "zrs",};render() {return (<div><buttononClick={() => {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()// 在构造器中修正thisthis.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>);}
    }
  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>事件对象与事件默认行为</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>

四、组件之间的通信

  1. 父传子

  • 概念:在使用子组件的时候,在子组件上自定义一个属性,然后把父组件里面的值作为属性值传给子组件,然后子组件使用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>)}
}
  • 父传子视图

  • 在这里插入图片描述

  1. 子传父

  • 概念:子传父就是在使用子组件的时候,将函数传给子组件,子组件触发该函数,修改父组件中的值

  • 子组件

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给faterMsggetMssage=(msg)=>{this.setState({fatherMsg:msg})}
}
  • 子传父图示

-在这里插入图片描述

  1. 兄弟组件传值

  • 概念:就是兄弟组件通过同一个父组件,一个子组件负责传值,另一个子组件负责接受参数

  • 父组件代码

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><buttononClick={() => {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>)}
}
  • 兄弟组件传参图示

  • 在这里插入图片描述

  1. 提供者和消费者

  • 提供者与消费者可用来实现跨级通信,提供者 provider 提供数据,消费者 consumer 使用数据。需要注意的是 provider 有一个固定的属性 valueconsumer 需要使用函数然后返回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}<buttononClick={() => {value.changInfo("12312314323454");}}>change</button></div>)}</Consumer>);}
}
  1. 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生命周期

  1. 概念:
  • React生命周期指 React组件实例从创建运行到销毁经历的一系列过程。
  • 注意react的函数式组件没有生命周期函数这一说,函数式组件要实现生命周期的功能,需要在副作用函数中实现。下面介绍的是类组件的生命周期函数。
  • 在这里插入图片描述
  1. 三种执行阶段

    1. 初始化阶段

- 先执行 `constructor` 函数 =》然后是 `render` 函数 =》然后是 `componentDidMount` 函数。/*** 这个函数会在render函数执行之后立即执行,* 1. 这时这个函数中可以执行一些关于dom的操作* 2. 也可以做一些请求后端数据的工作* 3. 也可以做一些定时器之类的活*/componentDidMount() {console.log("初始化阶段的最后一个执行函数");}
  1. 运行阶段

- 先执行render函数=》然后就是`componentDidUpdate `函数/*** 该函数有三个参数*  第一个参数是之前的属性*  第二个参数是之前的状态* * 在这个函数中做一些操作,都需要在判断条件中执行,不然很容易造成死循环*/componentDidUpdate(prevProps, prevState) {console.log(prevProps, prevState);console.log("更新阶段");}
  1. 销毁阶段

    1. 直接 componentWillUnmount 函数在,这个生命周期函数中做的事:
      1. 清除定时器
      2. 解绑dom事件
  //   这个函数在组件销毁的时候执行componentWillUnmount() {console.log("组件销毁了");}
  1. 完整的总代码演示

    1. 父组件
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 />}<buttononClick={() => {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><buttononClick={() => {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("组件销毁了");}}
  1. 在生命周期中创建和销毁一个定时器

    1. 父组件
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.flagflag = !flagthis.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

  1. hook简介:

    • Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。
    • Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React, Hook 是 React 16.8 的新增特性。
    • 常用Hook: useState() useEffect() useRef() useContext()
  2. hook特点:

    1. 在组件之间复用状态逻辑, 无需修改组件结构
    2. 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),而并非强制按照生命周期划分
    3. 不编写 class 的情况下使用 state 以及其他的 React 特性
  3. 使用state Hook:

    1. 在函数组件里没有this指向的问题,直接调用
    2. 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>
)
}
  1. Effect Hook(副作用)

    1. 函数组件主要作用是通过数据渲染UI界面,除了这个之外的操作就是副作用。

    2. ajax请求

    3. 手动修改dom

    4. localstorage操作

  2. 执行的时机

    1. 默认状态=>首次执行、每次组件更新
    2. 添加空[ ]=>首次执行
    3. 添加依赖项[count]=>首次执行、依赖项发生变化
  3. 普通的副作用

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>)
}

在这里插入图片描述

  1. 利用副作用清除定时器
    1. 父组件
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.flagflag = !flagthis.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>)
}

在这里插入图片描述

  1. hook之间的提供者和消费者传参

    1. 提供者
import React from "react";
// 引入子组件
import Demo from "./Son";// 创建一个 context 对象 导出一下,
// 因为子组件需要使用这个对象中的一个消费者对象
export const GlobalContext = React.createContext();export default function App() {return (<GlobalContext.Providervalue={{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>);
}
  1. 自定义hook
    1. 自定义hook文件(必须是use开头)

import { useState } from "react";
// 这个函数就是自定义的 hook 
export function useScrollTop() {// 还是定义一个useStateconst [height, setheight] = useState(0);// 只要检测到左边滑轮就设置一次setheightwindow.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'//引入一个高度样式height10000export default function ComC() {// 使用引入的useScrollTopconst [scrollTop,setscrollTop] = useScrollTop(0)return (<div className="h"><p>{scrollTop}</p></div>);
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部