React16新手教程记录

news2024/12/23 8:23:40

文章目录

  • 前言
  • 一些前端面试题
  • 1. 搭建项目
    • 1. 1 cdn
    • 1. 2 脚手架
  • 2. 基础用法
    • 2.1 表达式和js语句区别:
    • 2.2 jsx
    • 2.3 循环map
    • 2.4 函数式组件
    • 2.5 类式组件
    • 2.6 类组件点击事件
      • 2.6.1 事件回调函数this指向
      • 2.6.2 this解决方案
        • 2.6.2.1 通过bind
        • 2.6.2.2 箭头函数(推荐)
  • 3.state
  • 4. props
    • 4.1 props接受,校验
    • 4.2 props与state的区别
  • 5. refs
    • 5.1 字符串类型的ref(不建议使用字符串类型,性能影响)
    • 5.2 回调方法赋值
    • 5.3 createRef方法(只能放一个,class组件使用)
    • 5.4 useRef 方法(函数组件使用)
  • 6. 生命周期
    • 6.1 react16版本的生命周期
    • 6.2 react17版本的生命周期
  • 7. cdn源码文件
  • 8. 脚手架相关
    • 8.1 样式隔离
    • 8.2 组件通信
      • 8.2.1 父子组件通信(props)
      • 8.2.2 兄弟组件通信
      • 8.2.3 祖孙组件通信
    • 8.3 本地代理
      • 8.3.1 package.json
      • 8.3.2 http-proxy-middleware
  • 9. react-router(通过拦截浏览器路径变化)
    • 9.1 路由的概念
    • 9.2 路由的原理
    • 9.3 react-router-dom
      • 9.3.1 内置组件
        • 9.3.1.1 Link,Route ,BrowserRouter
        • 9.3.1.2 NavLink,Redirect,IndexRoute,Switch
        • 9.3.1.3 withRouter
      • 9.3.2 路由跳转参数
        • 1.params参数
        • 2.search参数
        • 3.state参数(和状态管理state无关)
        • 4.三种方式区别
      • 9.3.3 编程式导航
  • 10.redux
    • 10.1 三个概念
      • 10.1.1 store, action
      • 10.1.2 reducers
      • 10.1.3 state变化后触发render
    • 10.2 核心Api
  • 11.react-redux
  • 12.hooks(解决函数式组件的state,ref)
    • 12.1 useState
    • 12.2 useEffect(模拟生命周期)
    • 12.3 useRef
  • 13.扩展
    • 13.1 组件懒加载
    • 13.2 Fragment
    • 13.3 Context(祖孙组件通信)
    • 13.4 错误边界(Error Boundaries)
    • 13.4 PureComponent


前言

新手React上路:从建立项目开始

一些前端面试题

其他博主的面试记录

1. 搭建项目

1. 1 cdn

	// 可以访问react
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    // 可以访问ReactDOM
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    // babel插件
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>

1. 2 脚手架

命令行搭建项目:npm 5.2.0 以上版本,会自动安装npx。npx说白了就是会先查看安装包在不在。若不存在,npx将安装其最新版本,然后执行它;

# npm:构建一个my-app的项目
npm install -g create-react-app
create-react-app my-app

# npx:构建一个my-app的项目
npx create-react-app my-app

#进入项目进行编译
cd my-app
npm start

2. 基础用法

2.1 表达式和js语句区别:

js表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方。

a
a+b
map
methos
function(){}

js语句:js语法相关的代码

if
for
switch

2.2 jsx

使用{},内部放js表达式

        const user = {
            name: '罗测试',
            imageSize: 100,
            imageUrl: 'https://react.dev/_next/image?url=%2Fimages%2Fuwu.png&w=64&q=75'
        }
        const element1 =
            <div>
                <h1>普通的jsx:</h1>
                {/*class绑定使用className,属性,内联样式可以通过大括号{ }进行动态绑定*/}
                <img className="avatar" src={user.imageUrl} style={{
                    width: user.imageSize,
                    height: user.imageSize
                }} />
                {/*界面内容使用{ }动态绑定*/}
                <h1>
                    {user.name}
                </h1>
            </div>

        ReactDOM.render(element1, document.getElementById('app'))

2.3 循环map

const products = [
  { title: 'Cabbage', id: 1 },
  { title: 'Garlic', id: 2 },
  { title: 'Apple', id: 3 },
];
const listItems = products.map(product =>
  <li key={product.id}>
    {product.title}
  </li>
);

return (
  <ul>{listItems}</ul>
);

2.4 函数式组件

函数式组件: 首字母大写,小写会被视为html标签
可以通过参数操作props,但是ref和state不能使用修改

		function Head() {
            // this为undefined,因为babel翻译转换为严格模式,严格模式的this为undefined
            console.log('我是函数内部的this'+this)
            return <div>我是头部</div>
        }
        function Dom1() {
            return (
                <div>
                    <Head/>
                </div>
            )
        }
        /* 
            1.react解析组件标签,找到相关租价
            2.发现组件是用函数定义的,随后调用该函数。将返回的dom转换为真实dom
        */
        ReactDOM.render(<Dom1/>, document.getElementById('app'))

注意:函数时编程内部的this是undefined
在这里插入图片描述
在这里插入图片描述

2.5 类式组件

  • es6复习:
    1.类中的构造器不是必须要写的,要对实例进行一些初始化的操作才写
    2.如果a类集成了b类,且a写了构造器,那需要在构造器最上面添加super
    3.类中定义的方法,都是放在类的原型对象上,供实例使用
    4.类中的方法,使用实例调用指向的是实例,否则指向调用的对象
  • 类组件代码(必须要继承React.Component):
    1.constructor调用一次
    2.render调用1+n次,n是状态更新的次数
		// 类式组件: 必须要继承React.Component
        class Footer extends React.Component{
            // render 是放在 Footer组件 的实例对象上的,
            render(h) {
                console.log('我是类式组件render的this:',this)
                return <div className="text-center">我是底部</div>
            }
        }
        function Dom1() {
            return (
                <div>
                    <Footer/>
                </div>
            )
        }
        /* 
            1.react解析组件标签,找到相关租价
            2.1发现组件是用函数定义的,随后调用该函数。将返回的dom转换为真实dom
            2.2发现组件是用类定义的,随后new出来该类的实例。并通过实例调用原型上的render方法。将返回的dom转换为真实dom
        */
        ReactDOM.render(<Dom1/>, document.getElementById('app'))

2.6 类组件点击事件

2.6.1 事件回调函数this指向

class Container extends React.Component {
    constructor(props) {
        super(props)
    }
    changeHot() {
        console.log('我是类中方法的this值是undefined', this)
    }
    render(h) {
        return (
            <div>
                {/*state使用
                    1.通过this指向原型对象才能找到changeHot方法。
                    2.changeHot执行是作为onClick回调执行,不是通过实例执行。
                        所以changeHot内部this是直接调用所以指向window,但是因为babel,所以是undefined
                    3.
                */}
                <h1 onClick={this.changeHot}>1.今天天气好</h1>
            </div>
        )
    }
}

2.6.2 this解决方案

2.6.2.1 通过bind
class Container extends React.Component {
    constructor(props) {
        super(props)
        // 给实例对象添加了一个changeHot方法 = 修改changeHot函数内部的this,指向Container实例
        // bind返回构造函数,需要调用。call,apply是直接执行
        this.changeWeather = this.changeHot.bind(this);
    }
    changeHot() {
        console.log('我是类中方法的this值是实例', this)
    }
    render(h) {
        return (
            <div>
            	{/*通过bind修改changeHot内部this指向*/}
                <h1 onClick={this.changeWeather}>2.今天天气好</h1>
                <h1 onClick={this.changeHot.bind(this)}>3.今天天气好</h1>
            </div>
        )
    }
}
2.6.2.2 箭头函数(推荐)
class Container extends React.Component {
    //可以直接写赋值语句,是给实例上添加属性
    exTip = "今天天气好"
    // 使用箭头函数,定义时上层作用域中的this
    changeHotEasy = () => {
        this.setState({ 'isHot': !this.state.isHot })
    }
    changeHot() {
        console.log('我是类中方法的this值是实例', this)
    }
    constructor(props) {
	    super(props)
	    this.state = {
	    	isHot: true
	    }
    }
    render(h) {
    	return (
	    	<h1 onClick={this.changeHotEasy}>4.{exTip}{isHot ? '热' : '冷'}</h1>
	    	<h1 onClick={() => this.changeHot()}>5.{this.exTip}{isHot ? '热' : '冷'}</h1>
    	)
    }
}

3.state

状态不能直接更改,必须通过setState修改

class Container extends React.Component {
	//可以直接写赋值语句,是给实例上添加属性
    exTip = "今天天气好"
    state = {
	    isHot: true,
	    tips: '我很牛'
    }
    constructor(props) {
        super(props)
        // this.state = {
        //     isHot: true,
        //     tips: '我很牛'
        // }
    }
    changeHot() {
        // 状态不能直接更改,必须通过setState修改
        // this.state.isHot = false
        // setState是合并,不是赋值,修改isHot不影响tips
        this.setState({ 'isHot': !this.state.isHot })
        // 函数方式语法
        this.setState((state, props)=>{
        	return { conut: state.conut + 1 }
        })
    }
    render(h) {
        const { isHot, tips } = this.state
        return (
            <div>
            	<h1 onClick={() => this.changeHot()}>5.{this.exTip}{isHot ? '热' : '冷'}</h1>
            </div>
        )
    }
}	 		

4. props

4.1 props接受,校验

props是单项数据流,不能修改

// html引入限制库
<!-- 引入prop-type,用于组件标签props属性进行限制 -->
<script src="https://cdn.staticfile.net/prop-types/15.6.1/prop-types.js"></script>

//js添加
const products = [
    { title: 'Cabbage', id: 1 },
    { title: 'Garlic', id: 2 },
    { title: 'Apple', id: 3 },
]
class CardList extends React.Component {
    static propTypes = {
        // array,number,string,func,boolean...
        listItems: PropTypes.array.isRequired
    }
    static defaultProps = {
        listItems: [],
        name: '默认,就算没传,也是可以查到的'
    }
    render(h) {
        return (
            <div>
                {
                    this.props.listItems.map(item => {
                        return <div key={item.id}>{item.id}:{item.title}</div>
                    })
                }
            </div>
        )
    }
}
// 对标签属性进行数据类型,必填限制
// CardList.propTypes = {
//     // array,number,string,func,boolean...
//     listItems: PropTypes.array.isRequired
// }
// // 添加标签属性默认值
// CardList.defaultProps = {
//     listItems: []
// }
function Dom1() {
    return (
        <div>
            <CardList listItems={products} />
        </div>
    )
}
ReactDOM.render(<Dom1 />, document.getElementById('app'))

4.2 props与state的区别

props:指组件间传递的数据,由父对子进行传递。React的数据流是自上而下的,所以组件内部的props是只读的不可修改!
state:组件内部的数据,不能够直接修改,使用setState来改变数据。

5. refs

元素对应ref返回元素本身,组件返回组件实例

5.1 字符串类型的ref(不建议使用字符串类型,性能影响)

通过ref属性,绑定ref值。通过refs获取。

class Dom1 extends React.Component {
    getRefs = () => {
        console.log(this.refs);
    }
    render() {
        return (
            <div>
            	<Container ref="container" />
                <h1 ref="h1" onClick={() => this.getRefs()} > 点我市市</h1>
            </div>
        )
    }
}

在这里插入图片描述

5.2 回调方法赋值

在ref属性绑定值的时候通过回调函数赋值。(会调用多次)

class ContainerRef extends React.Component {
    // 回调赋值方式获取
    getH2 = () => {
        console.log(this.h2Ref);
    }
    render(h) {
        return (
            <div>
                <h2 ref={(event) => this.h2Ref = event} onClick={() => this.getH2()}> 点我市市2</h2>
            </div>
        )
    }
}

解决方案(调用多次):通过ref回调函数方式

class ContainerRef extends React.Component {
    getH2 = () => {
        console.log(this.h2Ref);
    }
    // 通过ref回调函数方式
    setRefH2 = (event) => {
        this.h2Ref = event
    }
    render(h) {
        return (
            <div>
                <h2 ref={this.setRefH2} onClick={() => this.getH22()}> 点我市市2.2</h2>
            </div>
        )
    }
}

5.3 createRef方法(只能放一个,class组件使用)

每个容器需要新建一个

		class ContainerRef extends React.Component {
            getRefs = () => {
                console.log(this.myRef1.current);
                console.log(this.myRef2.current);
            }
            // ======createRef方式获取=======
            myRef1 = React.createRef()
            myRef2 = React.createRef()
            render(h) {
                return (
                    <div>
                        <h1 ref={this.myRef1} onClick={() => this.getRefs()} > 点我市市3</h1>
                        <h1 ref={this.myRef2} onClick={() => this.getRefs()} > 点我市市4</h1>
                    </div>
                )
            }
        }

5.4 useRef 方法(函数组件使用)

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        聚焦这个输入框
      </button>
    </>
  );
}

6. 生命周期

6.1 react16版本的生命周期

在这里插入图片描述

// 挂载的流程

  1. constructor》
  2. componentWillMount(挂载前)》
  3. render》
  4. componentDidMount(挂载后)

// setState之后(手动更新)

  1. shouldComponentUpdate(默认返回真,控制是否更新视图)》
  2. componentWillUpdate(更新前)》
  3. render》
  4. componentDidUpdate(更新后)

// 强制更新(实例方法:forceUpdate)

  1. forceUpdate》
  2. componentWillUpdate…

// 父组件更新子组件的props,子组件会触发

  1. componentWillReceiveProps》
  2. shouldComponentUpdate…

// 卸载的流程

  1. componentWillUnmount(卸载前)》

// 手动卸载(卸载,ReactDOM方法)
unmountComponentUnmountAtNode

class ComponentsLive extends React.Component {
    state = {
        test: 0
    }
    constructor(props) {
        console.log('constructor');
        super(props)
    }
    // 挂载前
    componentWillMount() {
        console.log('componentWillMont');
    }
    // 挂载后
    componentDidMount() {
        console.log('componentDidMont');
    }
    changeTest = () => {
        console.log('调用setState了');
        this.setState({ test: this.state.test++ })
    }
    // 更新前
    componentWillUpdate() {
        console.log('componentWillUpdate');
    }
    // 更新后
    componentDidUpdate() {
        console.log('componentDidUpdate');
    }
    // 卸载前
    componentWillUnmount() {
        console.log('componentWillUpdate');
    }
    render() {
        console.log('render');
        return (
            <div onClick={this.changeTest}>生命周期</div>
        )
    }
}

在这里插入图片描述

6.2 react17版本的生命周期

在这里插入图片描述

调整3个:三个will生命周期前面添加UNSAFE_
componentWillMount》UNSAFE_componentWillMount
componentWillReceiveProps》UNSAFE_componentWillReceiveProps
componentWillUpdate》UNSAFE_componentWillUpdate
新增2个:
getDeriveStateFromProps():替换为componentWillMount的位置
getSnapshotBeforeUpdate():替换为componentWillUpdate的位置

7. cdn源码文件

github地址链接

8. 脚手架相关

8.1 样式隔离

在这里插入图片描述在这里插入图片描述

样式的内部用父级类名或者id标识做隔离
在这里插入图片描述
或者将css文件名前缀添加module,使用import {名称} form 'css地址'。然后类名使用{名称.属性名}写进className
在这里插入图片描述

8.2 组件通信

8.2.1 父子组件通信(props)

父传子:子通过props获取

//父组件
import React from "react"
import ChildComponent from "../childComponent"
class ParentComponent extends React.Component {
    state = {
        name: "parent",
        allList: [{ id: 0, name: "第一名" }, { id: 1, name: "第二名" }, { id: 2, name: "第三名" }]
    }
    //子传父:使用点击事件
    changeName(data) {
        this.setState({
            name: data //把父组件中的parentText替换为子组件传递的值
        });
    }
    //父传子:使用属性进行传参
    render() {
        const allList = this.state.allList;
        return (
            <div>
                <h1>{this.state.name}</h1>
                <ChildComponent allList={allList} changeName={(data) => this.changeName(data)} />
            </div>
        )
    }
}
export default ParentComponent;

子传父:子通过调用props的方法传递(父组件中定义好的)

// 子组件
import React from "react"
class ChildComponent extends React.Component {
    clickFun(text) {
        this.props.changeName(text)//把值传递给了props的事件当中
    }
    //使用属性进行传参
    render() {
        return (
            <div>
                <h1 onClick={() => { this.clickFun('变成子组件的数据') }}>点击改变父组件</h1>
                {/* 子组件通过props接受参数 */}
                {
                    this.props.allList.map((item) => {
                        return (<div key={item.id} >{item.name}</div>)
                    })
                }
            </div>
        )
    }
}
export default ChildComponent;

8.2.2 兄弟组件通信

  1. 通过props触发父组件,父组件在触发兄弟组件
  2. redux
  3. 消息订阅-发布(pubsub.js)
    pubsub.js的github地址

8.2.3 祖孙组件通信

  1. redux
  2. context生产者消费者模式
  3. 消息订阅-发布(pubsub.js)

8.3 本地代理

8.3.1 package.json

在这里插入图片描述

8.3.2 http-proxy-middleware

在src目录下创建一个setupProxy.js文件,必须是这个名称

const proxy = require('http-proxy-middleware')
module.exports = function (app) {
    app.use(
        proxy('/api', {
            target: 'https://api.zhiwucloud.com',
            changeOrigin: true,
            pathRewrite: {
                '^api': ''
            }
        })
    )
}

9. react-router(通过拦截浏览器路径变化)

9.1 路由的概念

1.什么是路由:

  • 一个路由就是一个映射关系
  • key为路径,value可能是function或者component

2.路由的分类:

  • 后端路由(是function,如接口)
  • 前端路由(component)

9.2 路由的原理

hash和history区别:地址栏上有#

// History用一个第三方插件history.js,封装的BOM的history
let history = History.creatBrowerHistory() // 使用的H5推出的history身上的API,可能旧浏览器不兼容
let history = History.creatHashHistory() // hash值锚点方式

封装的BOM的history,拦截history变化

// html代码
<a href="https://editor.csdn.net" onclick="return push('/test')></a>

// js代码
function push(path){
	// 界面栈添加一条路径记录
	history.push(path)
	// 不让浏览器进行界面跳转
	return false
}
// 界面栈替换当前
function replace(path){
	history.replace(path)
}
// 界面栈返回上一页
function back(){
	history.goBack()
}
// 界面栈前进一页
function forward(){
	history.forward()
}
history.listen(location)=>{
	console.log('路由发生变化啦,我监测到了')
}

9.3 react-router-dom

安装: npm install --save react-router-dom

9.3.1 内置组件

9.3.1.1 Link,Route ,BrowserRouter
  • BrowserRouter:Route,Link必须放在这个标签内部
  • Link:路由跳转,参数to是要展示的组件。replace属性接受布尔值,定义跳转是新增还是替换当前路径
  • Route:组件的内容展示,path与Link的to对应。exact属性:精准匹配(默认模糊匹配)
import './App.css'
import Home from './pages/home'
import About from './pages/about'
import { Link, BrowserRouter, Route } from 'react-router-dom'

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        跳转切换:
        <Link to="/about">跳转到about</Link>
        <Link to="/home">跳转到home</Link>
        {/* 内容区域 */}
        <div>
          <Route exact path="/about">
            <About />
          </Route>
          <Route exact path="/home">
            <Home />
          </Route>
        </div>
      </BrowserRouter>
    </div>
  );
}
export default App;

9.3.1.2 NavLink,Redirect,IndexRoute,Switch
  • NavLink:可以实现链接的高亮,通过activeClassName设置高亮样式名称
import { NavLink, Redirect, IndexRoute, Switch} from 'react-router-dom'
<NavLink activeClassName="active" to="/home">跳转到home</NavLink>
  • Redirect:重定向到其他 route 而不改变旧的 URL。
  • IndexRoute:默认路由
  • Switch(单一匹配):匹配到一个路由后不在匹配。
    下面代码如果不用switch,则dataTable和alarmManagement都会展示,加上switch则只展示dataTable
<Switch>
	<IndexRoute component={Home}/>
    <Redirect from="/ddd" to="/alarmManagement" exact/>
    <Route exact path="/dataTable" component={dataTable}/>
    <Route exact path="/dataTable" component={alarmManagement}/>
    <Route exact path="/dashboard" component={dashboard}/>
    <Route exact path="/*" component={notFound}/>
</Switch>
9.3.1.3 withRouter

withRouter: 让一般组件能使用路由组件的api

import { withRouter} from 'react-router-dom'
import React from "react"
class Head extends React.Component {
	routePush(){
		this.props.history.goBack()
	}
    render() {
        return (
            <div onClick={()=>this.routePush}>
                我是Head
            </div>
        )
    }
}
export default withRouter(Head)

9.3.2 路由跳转参数

在这里插入图片描述

1.params参数
// 跳转的时候添加参数
<Link to="/pw/pbzb/666"></Link>

// 注册路由的地方接受
<Route path="/pw/pbzb/:id" component={PwPbzb}></Route>

//PwPbzb组件内部接受
console.log(this.props.match.params)
2.search参数
// 跳转的时候添加参数,urlencode
<Link to="/pw/pbzb?name=百度&articleId=108198330"></Link>

//PwPbzb组件内部接受
import * as queryString from 'querystring'
const { name, articleId } = queryString.parse(this.props.location.search.slice(1))
3.state参数(和状态管理state无关)
// 跳转的时候添加参数
<Link to={{
  pathname: '/pw/pbzb',
  state: {
    fromDashboard: true,
  	articleId: '108198330'
  }
}} />

//PwPbzb组件内部接受
const { fromDashboard, articleId} = this.props.location.state || {}
4.三种方式区别

params,search参数地址栏会展示
state不会展示在地址栏:history模式下他是存储在history的。所以当浏览器缓存清空后,参数会丢失。hash模式下界面刷新会丢失

9.3.3 编程式导航

// 跳转方法
this.props.history.push('/pw/pbzb', {
	fromDashboard: true,
	articleId: '108198330'
 })
this.props.history.replace(path, state)
// history前进后退相关操作
this.props.history.go(n)
this.props.history.goBack()
this.props.history.forword()

10.redux

在这里插入图片描述

10.1 三个概念

10.1.1 store, action

组件获取state:store.getState()
触发action:store.dispatch(type, data)

import React from "react"
import store from "../../redux/store"

class Home extends React.Component {
    addCount() {
        store.dispatch('increment', 1)
    }
    render() {
        return (
            <div>
                获取store数据:{store.getState()}
                <button onClick={() => this.addCount()}>1</button>
            </div>
        )
    }
}
export default Home;

10.1.2 reducers

store.js

import { createStore } from 'redux'
import contReducer from './contReducer'
// 构建一个store并暴露,参数是reducer函数
export default createStore(contReducer)

contReducer.js

// 创建一个为count组件服务的reducer,本质就是一个函数
// 第一次调用是store自动触发的,preState是undefined
const initState = 0
export default function contReducer(preState = initState, action) {
    const { type, data } = action
    switch (type) {
        case 'increment':
            return preState + data
        case 'decrement':
            return preState - data
        default:
            return preState
    }
}

10.1.3 state变化后触发render

index.js

// 检查redux中状态的变化,只要有变化就会执行回调
import store from './redux/store'
store.subscript(() => {
  ReactDOM.render(<App />, document.getElementById('root'))
})

10.2 核心Api

  • createStore
  • getState

11.react-redux

在这里插入图片描述

12.hooks(解决函数式组件的state,ref)

12.1 useState

useState函数参数表示默认值,返回数组第一项是状态值,第二项是修改方法

import React, { useState } from "react"
// 调用1+n次
function Home(props) {
    // 第一次调用就存储了,后续调用Home的时候不会重置成0
    const [count, setCount] = useState(0)
    const [obj, setObj] = useState({
        myName: 'name1',
        age: 18
    })
    function changeCount() {
        // setCount(count+1)
        setCount((count) => count + 1)
    }
    function changeName() {
        setObj({
            ...obj,
            myName: 'name2'
        })
    }
    return (
        <div>
            我是函数式组件
            <div>
                state方式1:{count}
                <button onClick={changeCount}> 点我修改state </button>
                <br />
                state方式2:{obj.myName} {obj.age}
                <button onClick={changeName}> 点我修改state </button>
            </div>
        </div>
    )
}

export default Home;

12.2 useEffect(模拟生命周期)

接受两个参数:回调函数,监听数组

  • 第一个参数:
    返回函数相当于componentWillOnmount
  • 第二个参数:
    如果没有传,监听所有变化执行。
    如果传空数组,那回调指挥在第一次render后执行。
    如果传了数组项,就是监听对应数组项的变化。
// 第二个参数空数组相当于componentDidMount, componentDidUpdate
useEffect(() => {
    let timer = setInterval(() => {
        setCount((count) => count + 1)
    }, 1000)
    // useEffect返回的函数相当于componentWillOnmount
    return () => {
        clearInterval(timer)
    }
}, ['count'])

12.3 useRef

const myRef = useRef()
function getRefValue() {
    alert(myRef.current.value)
}
return (
	<div>
		<input ref={myRef}></input>
		<button onClick={getRefValue}> 点我弹出input的值 </button>
	</div>
)

13.扩展

13.1 组件懒加载

使用的时候在加载

import React, { lazy } from 'react'
const Home = lazy(() => import('./Home'))

13.2 Fragment

Fragment标签不会编译到dom中

<Fragment></Fragment>
// 或者使用空标签,空标签不能传递属性,Fragment可以传key属性
<></>

13.3 Context(祖孙组件通信)

Context API 用于在组件树中共享全局数据,避免了通过层层传递 props 的繁琐操作。

  1. createContext.Provider +useContext
const MyContext = React.createContext('default');
class App extends React.Component {
  render () {
    return (
      <MyContext.Provider value={{ color: 'red' }}>
        <Child />
      </MyContext.Provider>
    ); 
  }
}
const value = React.useContext(MyContext);
  1. createContext.Consumer

13.4 错误边界(Error Boundaries)

错误边界是一种用于捕获子组件渲染过程中发生的错误,并展示备用 UI 的机制。componentDidCatch捕获异常

componentDidCatch(error, info) {
    this.setState({ hasError: true });
}

13.4 PureComponent

默认实现的shouldComponentUpdate方法中自动进行浅比较props和state,从而判断是否需要重新渲染组件。Component 的shouldComponentUpdate默认就是true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2097054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL数据库增删查改(基础)CRUD

CRUD 即增加 (Create) 、查询 (Retrieve) 、更新 (Update) 、删除 (Delete) 四个单词的首字母缩写。 1. 新增&#xff08;Create&#xff09; 1.1单行数据&#xff08;全列插入&#xff09; 比如说&#xff1a;创建一张学生表&#xff0c;有姓名&#xff0c;学号。插入两个学…

C++和OpenGL实现3D游戏编程【连载7】——文字和汉字的显示

1、本节实现的内容 上一节我们讨论了纹理在二维平面内不规则图形贴图的相关基础操作,本节我们开始了解游戏里文字以及汉字的显示方法。本节课我们将从基本的ASCII字符显示,拓展到中文字符的显示,最后再讲到纹理字符的显示,并对各种文字显示方法的优缺点和使用场景进行分析…

改进YOLO的群养猪行为识别算法研究及部署(小程序-网站平台-pyqt)

概述 群养猪的运动信息和行为信息与其健康状况息息相关&#xff0c;但人工巡视费时费力&#xff0c;本实验提出采用行为识别算法于群养猪的养殖管理中&#xff0c;识别群养猪drink&#xff08;饮水&#xff09;、stand&#xff08;站立&#xff09;和lie&#xff08;躺卧&#…

[STM32]从零开始的STM32标准库环境搭建(小白向)

一、我们为什么要搭建STM32标准库开发环境 如果你对STM32有一定的了解&#xff0c;相信你已经认识了STM32的几种开发方式。基于STM32寄存器开发&#xff0c;基于ST官方的标准库开发&#xff0c;基于ST官方的HAL库开发。我们现在来了解一下这些库的优缺点。首先就是基于寄存器开…

【计算机组成原理】七、输入/输出系统:1.I/O基本概念、I/O设备(外部设备)

七、输入/输出系统 文章目录 七、输入/输出系统1.基本概念4. I/O设备&#xff08;外部设备&#xff09;4.1输出设备4.1.1键盘4.1.2鼠标 4.2输出设备4.2.1显示器4.2.2打印机 4.3外存设备 1.基本概念 “I/O”就是“输入/输出”( Input/Output)。 I/O系统由I/O软件和I/O硬件两部分…

精益管理:怎样选择适合的库存管理策略?

如果顾客在下单后愿意耐心等待产品制作完成&#xff0c;对于生产管理者而言&#xff0c;自然是最为方便的。一般而言&#xff0c;水电工程行承接的订单&#xff0c;顾客都只能耐心等待工作完成&#xff1b;但这只是个别情况&#xff0c;实际上大部分顾客并没有这么多耐心&#…

【k8s系列】Kubernetes Service 深度解析:从基础到实战

一、前言 在当今的云原生世界中&#xff0c;Kubernetes 已经成为容器编排和管理的事实标准。它提供了一种强大的方式来部署、扩展和管理容器化应用。然而&#xff0c;随着应用规模的扩大和复杂性的增加&#xff0c;如何有效地暴露和管理这些应用的网络服务成为了一个关键问题。…

Google Gemini 使用 | 中小型企业借助谷歌 Gemini 提高生产力的 5 种方法

Gemini Business for Workspace 融合了谷歌最强 AI 技术&#xff0c;并集成到办公产品组件中的解决方案。 无论是中型的家族企业&#xff0c;还是刚起步的小型创业团队&#xff0c;你们是否觉得一天 24 小时根本不够用&#xff1f;既要忙着客户维系和拉新&#xff0c;又要管理员…

pda移动护理终端医用手持机

随着物联网技术的发展&#xff0c;智能设备之间形成了紧密的网络互联。 医疗行业越来越注重智能设备的使用&#xff0c;医用手持机可以采集病人、药品、材料等信息&#xff0c;很大程度地改善了医院患者的管理&#xff0c;进一步提升医护人员的工作效率。 医护人员通过使用pda移…

【开学季】告别一次性AI写作工具,打造你自己的专属AI助手!

新学期的钟声敲响&#xff0c;校园里充满了书本的香气和求知的热情。&#x1f4da;可许多学生和职场人士&#xff0c;仍然依赖那些一次性的AI写作工具来完成自己的写作任务。我想问你&#xff1a;为什么不尝试自己构建一个属于自己的AI写作工作流呢&#xff1f;&#x1f914; 前…

机器学习:自然语言处理之关键词提取(TF-IDF)

目录 前言 一、TF-IDF 1.TF 2.IDF 3.TF-IDF计算法则 4.TF-IDF的本质 二、代码实现 1.导入库 2.读取文本数据 3. 初始化TfidfVectorizer并转换文本数据 4. 获取词汇表并创建 DataFrame 5.处理每篇文章的特征 总结 前言 TF-IDF&#xff08;Term Frequency-Inverse D…

MySql字段有null值与其他值的比较

MySql字段有null值与其他值的比较 SELECT count(1)在这里插入代码片FROM LAW_ENFORCEMENT_TROUBLE TBWHERE TB.STATUS 1AND TB.DUTY_LIMIT_DATE < NOW()AND TB.TROUBLE_STATUS ! 2查出结果为0条&#xff0c;但是应该为3条&#xff0c;查看表数据发现&#xff0c;TROUBLE_S…

常见图像图片属性的介绍与说明

图像属性是指图像的一些基本特征和参数&#xff0c;它们定义了图像的外观和存储方式。以下是一些常见的图像属性&#xff1a; 1. 分辨率&#xff1a; 分辨率通常以像素数&#xff08;如800x600&#xff09;来表示&#xff0c;指的是图像的宽度和高度上的像素点数。分辨率越高&…

mysql5.7 TIMESTAMP NOT NULL DEFAULT ‘0000-00-00 00:00:00‘ 换版8版本 引发的问题

mysql5.7 TIMESTAMP NOT NULL DEFAULT 0000-00-00 00:00:00 换版引发的问题 问题背景sql_mode上机演示5.78.4 问题背景 在项目mysql版本由5.7 换版到8.4版本后&#xff0c;我们进行回归测试时&#xff0c;却发现一个积年代码报错了&#xff0c;是数据库插入报的错 xxx can not…

自用Office 365家庭版全家桶 + OneDrive 1TB拼车,40/年,来长期拼的!

自用Office 365家庭版全家桶 OneDrive 1TB拼车&#xff0c;40/年&#xff0c;来长期拼的! &#x1f50d;1.背景描述&#x1f50d;&#x1f421;2. 常见问题解答&#x1f421;【问】是正版吗&#xff1f;【问】跟普通版本有什么区别&#xff1f;【问】会不会是假货? &#x1f…

1、Java简介+DOS命令+java的编译运行(字节码/机器码、JRE/JVM/JDK/JIT的区别)+一个简单的Java程序

前言&#xff1a;本文属于黑马程序员和javaguide的混合笔记&#xff0c;仅作学习分享使用&#xff0c;建议感兴趣的小伙伴去看黑马原视频或javaguide原文。如有侵权&#xff0c;请联系删除。 Java类型&#xff1a; JavaSE 标准版&#xff1a;以前称为J2SE&#xff0c;主要用来…

掌握一招:‌输入什么命令,‌轻松查看电脑IP地址?‌

在日常使用电脑的过程中&#xff0c;‌无论是进行网络设置、‌远程连接还是解决网络问题&#xff0c;‌了解并查看自己的电脑IP地址都是一项基础且重要的操作。‌对于许多用户来说&#xff0c;‌可能并不清楚如何快速准确地获取这一信息。‌本文将为你揭秘一个简单实用的命令&a…

【数据结构与算法】:十大经典排序算法

文章目录 前言一、冒泡排序&#xff08;Bubble Sort&#xff09;1.1 冒泡排序原理1.2 冒泡排序代码1.3 输出结果 二、选择排序&#xff08;Selection Sort&#xff09;2.1 选择排序原理2.2 选择排序代码2.3 输出结果 三、插入排序&#xff08;Insertion Sort&#xff09;3.1 插…

可重入VI,VI模板和动态VI之间的差异 转

可重入VI 当您想要同时运行同一VI的多个实例时&#xff0c;将使用可重入VI。当VI不可重入时&#xff0c;VI只有一个数据空间。因此&#xff0c;一次只能有一个调用者运行VI&#xff0c;因此调用者可能必须“等待轮到它”时才能使用VI。这是VI的默认选项&#xff0c;但您可以将V…

精通大模型:八本必读书籍,一篇搞定所有知识点!

如果你想深入了解大模型领域&#xff0c;无论是为了学术研究还是实际应用&#xff0c;选择合适的书籍是非常重要的。以下是精选的八本大模型相关书籍&#xff0c;涵盖了从基础理论到高级实践的内容&#xff0c;可以帮助你构建全面的知识体系。 《大模型应用开发极简入门》 简介…