React 学习笔记总结(七)

news/2024/12/23 1:10:32/

针对React拓展相关的学习。

文章目录

  • 一. React 项目打包
  • 二. React扩展 之 setState两种写法
  • 三. React扩展 之 lazyLoad(懒加载)
  • 四、React的 stateHook
  • 五、React 的 Effect Hook
  • 六、React 的 RefHook
  • 七、React 的 Fragment
  • 八、React 的 Context
  • 九、React 的 PureComponent
    • 1. Component组件的两个问题
    • 2. PureComponent 纯组件
  • 十、React 的 render props
    • 1. 组成父子组件的 两种方式
    • 2. render props 的 使用
  • 十一、React 的 ErrorBoundary
  • 十二、React 组件通信方式总结

一. React 项目打包

安装serve,该库的作用可以将一个静态页面作为一台服务器启动。方便测试打包后的html页面。

# 安装serve
npm i serve
# 执行serve,在对应打包后的目录下,执行serve命令
serve 

二. React扩展 之 setState两种写法

第一种写法:就是传对象。
在这里插入图片描述

setState方法的两个参数:

import React, {Component} from 'react';export default class Demo extends Component {state = {count:0}add = () => {const {count} = this.state// 更新状态 , 第二个参数callback是回调函数this.setState({count:count+1},() => {// fixme state状态改完,render页面刷新完,才调用该回调函数})// 因为,setState所调用的形式是异步的。console.log('此时state中的count值并没有变化:',this.state.count)}render() {return (<div><h1>当前求和为:{this.state.count}</h1><button onClick={this.add}>1</button></div>);}
}

第二种写法:传递函数。

  • 函数式setState: 好处拿到了state和props。也方便维护。
import React, {Component} from 'react';export default class Demo extends Component {state = {count:0}add = () => {const {count} = this.state// 函数式setState: 好处拿到了state和propsthis.setState((state,props) => {console.log('state',state)console.log('props',props)return {count:count+1}})console.log('此时state中的count值并没有变化:',this.state.count)}render() {return (<div><h1>当前求和为:{this.state.count}</h1><button onClick={this.add}>1</button></div>);}
}

使用原则:

  • 如果新状态不依赖于原来状态。 推荐使用对象方式。
  • 如果新状态依赖与原来状态。 推荐使用函数方式。(例如:上面自动+1效果)。

注意:如果需要在setState()执行后获取最新的状态数据,要在第二个callback函数中进行读取操作取。

三. React扩展 之 lazyLoad(懒加载)

一般项目特别大,组件特别多,都会用到懒加载这个东西。

例如:一个页面涉及到了20多个路由页面,但是用户仅仅用了3个,然而,加载的时候缺加载了20多个路由页面,这样就不太好。

所以,就要用懒加载。

案例如下:

  • 通过使用lazy和Suspense来进行操作。
// fixme 1. 引入lazy,Suspense
import React, {Component,lazy,Suspense} from 'react';
import { NavLink, Route} from 'react-router-dom'// fixme 2. 路由组件不要用引入的方式
// import About from '../2_lazyLoad/About'
// import Home from '../2_lazyLoad/Home'// fixme 注意: fallback中的内容组件必须是就位的,不能又使用import()函数,所以最好是提前引入
import Load from '../components/Load/Load'// fixme 3. 定义成函数并且使用import()函数操作
const Home = lazy(() => {// 使用import()函数来引入return import('../2_lazyLoad/Home')
})
const About = lazy(() => {// 使用import()函数来引入return import('../2_lazyLoad/About')
})class Demo extends Component {render() {return (<div style={{textAlign:"center"}}><div style={{textAlign:"center"}}><h1>React Router Demo</h1></div><div style={{textAlign:"center"}}>{/*{React靠路由跳转}*/}<NavLink to="/about">About</NavLink><br/><NavLink to="/home">Home</NavLink></div><div style={{textAlign:"center"}}>{/* fixme 4. 使用Suspense来包裹Route,fallback显示的是加载完成前的操作。注意:fallback中的内容组件必须是就位的,不能又使用import()函数 */}<Suspense fallback={<Load/>}>{/* 注册路由: 注意route和Router区分 */}<Route path="/about" component={About}/><Route path="/home" component={Home}/></Suspense></div></div>);}
}export default Demo;

四、React的 stateHook

Hook是React 16.8.0版本新增加的一个特性。

可以让函数组件中使用state以及其他的React属性(例如:生命周期钩子函数之类的。)。

三个常用的Hook:

  • State Hook: React.useState()
  • Effect Hook:React.useEffect()
  • Ref Hook:React.useRef()

State Hook的使用:

import React from 'react';/*** 函数式组件*/
function Index(){console.log('组件调用次数是 n + 1 次,第一次进入页面1次,之后render渲染n次。')/*** React.useState(0): 第一个参数代表初始值* 返回值是个数组:第一个是状态state值,第二个是函数(负责更新状态state值)。*/const [count,setCount] = React.useState(0)const [name,setName] = React.useState("Tom")function add(){console.log('+++')// setCount第一种写法:(值写法)setCount(count + 1)// setCount第二种写法:(函数写法) 可以更好维护setCount(preCount => (preCount + 1))}function update(){setName('Jerry')}return (<div><h2>当前求和为:{count}</h2><h2>我的名字是:{name}</h2><button onClick={add}>点我 + 1</button><button onClick={update}>修改名字</button></div>)
}export default Index;

五、React 的 Effect Hook

Effect Hook的使用:

import React from 'react';
import ReactDOM from 'react-dom'/*** 函数式组件*/
function Index(){const [count,setCount] = React.useState(0)/*** React.useEffect函数作用:就是实现了类函数中的componentDidMount之类的钩子函数了。*  但是用法很不同: 第一个参数(函数):是要执行的函数。 第二个参数(数组):是要监听哪个状态值。*/React.useEffect(()=>{let timer = setInterval(()=>{setCount(count => count + 1)},1000)// fixme 此处的返回值就是等于componentWillUnmountreturn () => {console.log('@@@')clearInterval(timer)}},[count])/*** 还有一种情况,像定时器之类的,在离开页面前需要关闭定时器。*  一般对象组件就直接在使用componentWillUnmount组件就可以了。**/function  unmount(){// 通过使用ReactDOM.unmountComponentAtNode来卸载组件ReactDOM.unmountComponentAtNode(document.getElementById('root'))}function add(){setCount(preCount => (preCount + 1))}return (<div><h2>当前求和为:{count}</h2><button onClick={add}>点我 + 1</button><button onClick={unmount}>卸载Root</button></div>)}export default Index;

可以把 useEffect Hook 看做对象组件如下三个钩子函数的组合:

  • componentDidMount()
  • componentDidUpdate()
  • componentWillUnmount()
语法和说明: 
useEffect(() => { // 在此可以执行任何带副作用操作return () => { // 在组件卸载前执行// 在此做一些收尾工作, 比如清除定时器/取消订阅等}
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行

六、React 的 RefHook

类式组件使用ref:

/*** 类式组件:*/
class Index extends React.Component {state = {count:0}// fixme 创建一个refmyRef = React.createRef()alertRef = () => {alert(this.myRef.current.value)}add = ()=> {this.setState(state => ({count:state.count + 1}))}render() {return (<div><input type="text" ref={this.myRef}/><h2>当前求和为:{this.state.count}</h2><button onClick={this.add}>点我 + 1</button><button onClick={this.alertRef}>提示</button></div>);}
}

RefHook的使用:

(1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作用:保存标签对象,功能与React.createRef()一样

七、React 的 Fragment

Frgament用法:

import React, {Component,Fragment} from 'react';class Index extends Component {render() {return (// 这样就不用写一个div了。<Fragment><input type="text"/></Fragment>);}
}export default Index;

空标签的用法:

import React, {Component,Fragment} from 'react';class Index extends Component {render() {return (// fixme 也可以使用一个空标签<><input type="text"/></>);}
}export default Index;

Fragment 与 空标签 区别:

  • 作用相同,但是Fragment可以有一个key属性,作为唯一标识使用(只有key属性)。

八、React 的 Context

context是 一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信。

考虑两种情况:

  • 对象式组件 和 函数式组件,不过一般项目中使用了redux就不会使用该方式了。
1) 创建Context容器对象:const XxxContext = React.createContext()  2) 渲染子组时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:<xxxContext.Provider value={数据}>子组件</xxxContext.Provider>3) 后代组件读取数据:// fixme 第一种方式:仅适用于类组件 static contextType = xxxContext  // 声明接收contextthis.context // 读取context中的value数据// fixme 第二种方式: 函数组件与类组件都可以<xxxContext.Consumer>{value => ( // value就是context中的value数据要显示的内容)}</xxxContext.Consumer>

九、React 的 PureComponent

1. Component组件的两个问题

1. 只要执行setState(),即使不改变状态数据, 组件也会重新render() ==> 效率低。

2. 只当前组件重新render(), 就会自动重新render子组件,纵使子组件没有用到父组件的任何数据。 ==> 效率低。

上面就会导致效率降低的情况。

导致上面情况的发生,因为,Component中的shouldComponentUpdate()钩子函数总是返回true。
在这里插入图片描述

2. PureComponent 纯组件

使用PureComponentPureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true注意: 只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false  不要直接修改state数据, 而是要产生新数据
项目中一般使用PureComponent来优化

注意:不要直接修改state数据,直接修改state虽然属性变了,但自身对象地址未发生变化(也就是个浅赋值),而是要产生新数据,不然PureComponent无法检测到。
在这里插入图片描述
还是要注意纯组件失效不更新的情况。

十、React 的 render props

1. 组成父子组件的 两种方式

第一种方式:
在这里插入图片描述
第二种方式:
在这里插入图片描述
注意:第二种方式有瑕疵,那么\<B name={this.state}/\>的this指向的是谁?此处便是缺点。

2. render props 的 使用

// 比较Vue 和 React:
Vue中: 使用slot技术, 也就是通过组件标签体传入结构  <A><B/></A>
React中:使用children props: 通过组件标签体传入结构使用render props: 通过组件标签属性传入结构,而且可以携带数据,一般用render函数属性

在这里插入图片描述

// 其实render prop就是为了解决如下情况:
<A><B>xxxx</B>
</A>
{this.props.children}
问题: 如果B组件需要A组件内的数据, ==> 做不到 

十一、React 的 ErrorBoundary

错误边界(Error boundary):用来捕获后代组件错误,渲染出备用页面,实际上就是有一个出错后能显示的页面。

只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误。

通过getDerivedStateFromError配合componentDidCatch来实现:

class Index extends Component {state = {hashError:'' // 用于标识子组件是否产生错误}// 生命周期函数,一旦后台组件报错,就会触发static getDerivedStateFromError(error) {console.log(error);// 在render之前触发// 返回新的statereturn {hasError: true,};}// 将错误信息返回后台(需要的话。)componentDidCatch(error, info) {// 统计页面的错误。发送请求发送到后台去console.log(error, info);}render() {return (<div><h3>组件</h3>{this.state.hashError ? <h2>当前不稳定,请稍后重试!</h2> : <Child/>}</div>);}
}

十二、React 组件通信方式总结

在这里插入图片描述


http://www.ppmy.cn/news/11711.html

相关文章

windows排查问题常用命令

查看JAVA进程占用PID: wmic process where caption"java.exe" get processid,caption,commandline /value查看进程端口信息&#xff1a;netstat -ano 或者 netstat -ano|findstr "8080" 或查看成功建立连接的&#xff1a;netstat -ano | findstr “ESTABLI…

本地小说阅读网站打造

目录 一、本地小说网站总体组织框架 1、所需的VUE库和elementLib以及JQ库 2、本地目录设计 3、整体代码样式 二、正文核心代码 1、引入element 样式&#xff0c;和自定义的样式 2、引入JS 3、自定义Header组件 1&#xff09;vue 定义MyHeader组件 2&#xff09;MyHead…

Vue项目大概目录介绍

后端,自己学习做个记录.实话是看不懂全靠抄. 这是一个刚建好的Vue项目 node_modules:整个项目用到的依赖文件 public--->favicon.ico:Vue的图标 public--->index.html:可以理解为首页入口,模板页,开发的时候用不到,Vue是个单页面应用,开发也用不到 src:好比项目的源码…

【Linux】编译器 - gcc 函数库

目录 一、背景知识 二、gcc如何执行 1、预处理 2、编译 3、汇编 4、链接 三、函数库 1、初识函数库 2、动静态库 2.1、动态库 2.2、静态库 2.3、动静态库的选择 一、背景知识 使用 vim 编辑器完成代码书写之后&#xff0c;我们需要使用 Linux 中的编译器 gcc 来对…

【K3s】第14篇 使用外部数据库PostgreSQL实现高可用安装部署k3s(详细步骤)

目录 1、外部数据库PostgreSQL安装 手把手教学PostgreSQL 解决“psql: error: could not connect to server: 拒绝连接”

荣誉+1,龙蜥社区荣登 CSDN 2022 中国开发者影响力年度榜单

近日&#xff0c;CSDN 在北京成功举行 “2022 中国开发者影响力盛典暨 CSDN 企业生态汇”活动&#xff0c;同时正式发布 2022 中国开发者影响力年度榜单。凭借本年度在开源领域的卓越贡献和技术实力&#xff0c;龙蜥社区荣登 CSDN 2022 “年度开发者社区” 榜单。&#xff08;图…

为什么在Java7中Switch语句支持String而不支持long呢?

目录 Switch语句长啥样&#xff1f; Switch支持字符以及字符串的底层原理 为什么不支持long类型呢&#xff1f; Switch语句长啥样&#xff1f; public static void main(String[] args) {int num 1;switch (num) {case 1:System.out.println("a");break;case 2:S…

C语言进阶——通讯录

目录 一. 整体框架 二. 添加联系人信息 三.显示所有联系人信息 四. 删除指定联系人信息 五. 查找指定联系人信息 六. 修改指定联系人 七 . 清空所有联系人 八. 以名字排序所有联系人 学习了结构体之后&#xff0c;我们便可以来实现一个简易的通讯录 这个…