React核心基础(上)

13 篇文章 0 订阅
1 篇文章 0 订阅

React的核心基础笔记

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

一、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>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>
    
  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>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>
      
  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>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>
      
  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 = 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>
      
  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>
        <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>
        );
      }
    }
    
    
  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给faterMsg
  getMssage=(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>
        <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>
    )
  }
}
  • 兄弟组件传参图示

  • 在这里插入图片描述

  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}
            <button
              onClick={() => {
                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 />}

        <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("组件销毁了");
  }
    
}

  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.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

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

在这里插入图片描述

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

    1. 提供者
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>
  );
}
  1. 自定义hook
    1. 自定义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>
  );
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端达闻西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值