软件开发定制React教程(详细版)

一、简介(背景)

软件开发定制本文篇幅较多,软件开发定制建议耐心看完,软件开发定制我相信多少会对你有所帮助!

1.1、概念

软件开发定制它是一个将数据渲染为HTML视图 的js库

1.2、原生js痛点

  • 用dom的API去操作dom,软件开发定制繁琐且效率低
  • 用js直接操作dom,软件开发定制浏览器会进行大量的回流和重绘
  • 原生js软件开发定制没有组件化的编程方案,软件开发定制代码复用性低,软件开发定制哪怕有模块话的概念,软件开发定制但模块化也只能拆解一个个js,软件开发定制对样式和结构也没办法拆解,软件开发定制组件化就相当于3软件开发定制剑客整体拆解,软件开发定制成为一个个的小功能

1.3、特点

  • 软件开发定制采用组件化模式,软件开发定制声明式编码,软件开发定制提高开发效率和组件复用性
  • 在React Native中可以用react软件开发定制预发进行安卓、ios软件开发定制移动端开发
  • 使用虚拟dom和有些的diffing算法,软件开发定制尽量减少与真实dom的交互,提高性能

二、React初体验

2.1、html中使用react

需求:往div软件开发定制中添加一个h1标签

代码注解:软件开发定制这里涉及到3个库文件,一个react(核心库),react-dom(用于支持react操作dom的)还有一个babel(将jsx语法转成js语法,软件开发定制因为浏览器只能识别js),还有就是script标签中的type需要写成text/babel,因为script软件开发定制标签中要写jsx的语法,软件开发定制这里再说一点,软件开发定制就是你引入了react-dom库,软件开发定制就可以使用ReactDOM变量了,软件开发定制跟以前学习jquery一样,引入jquery软件开发定制文件就可以使用$和jquery软件开发定制是同样的道理

2.1.1、 创建虚拟dom的方式

①使用原生js软件开发定制的方式去写(一般不用)

代码注解:使用原生js软件开发定制来创建虚拟dom时,此时script标签的type软件开发定制就不需要写成text/babel,软件开发定制写成原来的text/javascript就可以了,软件开发定制同时也可以删除babel库了,软件开发定制因为不需要它进行转换,软件开发定制浏览器本身就能识别

②使用jsx语法创建(软件开发定制就是最开始的那种方式)

软件开发定制这里可能会有小伙伴会问,软件开发定制为什么不用js来创建dom呢?软件开发定制我看写起来也还行啊,软件开发定制这是因为你还没见过结软件开发定制构嵌套的情况,软件开发定制当需求改为h1软件开发定制标签内再嵌套一个span标签,你怎么办?软件开发定制是不是后面还得再继续套React.createElement(‘span’,{},‘span内容’) ,软件开发定制那如果继续嵌套呢?软件开发定制是不是废了。。。,软件开发定制所以这里就能看出jsx的好处了,其实babel将jsx软件开发定制转换后的代码就相对于用原生js写的那样,软件开发定制只不过这些不用你写,babel帮你转换

2.1.2、 关于创建的虚拟dom

  1. 本质上其实就是一个object对象;
  2. 虚拟dom上的属性比较少,真实dom属性多,因为虚拟dom只在recat内部使用,用不到那么多的属性
  3. 虚拟dom最终会被react转换成真实dom,呈现再页面上

2.2、JSX语法

  • 定义虚拟dom时不要用引号
  • 标签中引入js表达式要用{}
  • 如果在jsx要写行内样式需要使用style={{coler:red}}形式
  • 样式的类名指定不能写class,要写className;
  • 只有一个根标签
  • 标签必须闭合
  • 标签首字母
    ①若小写字母开头,则会将该标签转为html同名标签,如果没找到,则会报错;
    ②若大写字母开头,则会认为是组件,它就会去找对应的组件,如果没找到,就会报组件未定义的错误;

三、React面向组件编程

3.1 安装开发者工具(React Developer Tools )

这里工具的具体安装方式就不多说了,由两种方式,一种是翻墙,直接在chrome浏览的商城去下载,还有一种方式是在浏览器扩展程序中打开开发者模式,然后导入已下载的插件文件即可

3.2 组件的分类

1. 函数式组件(适用于简单组件)

2. 类式组件(适用于复杂组件)

3.3 组件实例对象的三大属性

3.3.1、 state

这里我们用一个小需求来说说state和组件内绑定方法这两个问题,需求:点击文本,改变天气状态

上述图片中的例子这样的写法并不能实现我们的需求,为什么?因为changeWeather方法中打印的this是undefined,不是该weather组件的实例对象,自然也就无法拿到该实例对象上的state等属性,更加不用说去改变state中的状态了。。。那为什么会这样的?原因就写在图中,那我们要怎么处理才能让该方法拿到该组件的实例对象呢?来,看下面。。

在构造函数中加一句这个语句就可以了,那这行代码是什么意思呢?
构造函数中的this永远指向该组件的实例对象,所以=右侧意思就是该组件实例对象自身此时还没有该方法,他就会去原型对象上看有没有,显然这里是有的,然后调用bind方法,该方法做两件事,一、创建一个新的函数;二、函数内的this指向bing()括号中传入的,显然这里是组件实例对象;右侧执行完后,将该方法赋值给了实例对象本身的一个方法名(changeWeather),这样实例对象本身就有一个changeWeather方法了,并且内部this就是组件实例对象,所以此时render中点击调用的那个方法,实际上是this实例对象自身的一个changeWeather方法,而不是写在类中的那个原型对象上的changeWeather方法,我们为了不混淆两个重名的方法,我们区分看一下


好了,接下来我们要做改变状态这件事了,我们要通过react中的内置API(setState方法),不能直接更改state,就像下面这样。

好了,到现在需求已经满足了,但我们要对其简化。。。

上述将state和自定义方法直接写在了类中,这样写的意思就是说,给类组件的实例对象添加了一个state属性和自定义方法,而且这里的自定义方法必须写成箭头函数的形式,因为箭头函数内部是没有this指向的,他会去他外部找this,那此时外部的this就是组件实例对象

总结:

  • state是组件实例对象最重要的属性,必须是对象的形式

  • 组件被称为状态机,通过更改state的值来达到更新页面显示(重新渲染组件)

  • 组件render中的this指的是组件实例对象

  • 状态数据不能直接赋值,需要用setState()

  • 组件自定义方法中的this为undefined,怎么解决?

    ①将自定义函数改为表达式+箭头函数的形式(推荐)
    ②在构造器中用bind()强制绑定this

3.3.2、 props

props就是在调用组件的时候在组件中添加属性传到组件内部去使用

简单demo:

接下来这里我们想对传入的props属性进行一些必传、默认值、类型的校验,所以就需要用到一个prop-types库

下载:npm i prop-types --save
引入:import PropTypes from ‘prop-types’


构造器问题

构造器仅用于以下两种情况:

  • 通过this.state赋值对象来初始化内部的state
  • 为事件处理函数绑定实例(就是上面的this.changeWeather=this.changeWeather.bind(this))

但是上述的这两个点我们都有简单的方法来实现,state我们可以用state={name:11}这种直接赋值的方式来实现,自定义事件的话可以通过赋值语句+箭头函数的方式来实现,所以一般开发过程中都不写构造器,还有就是如果一定要写构造器,那么构造器是否接受props,是否传递给props,取决于是否要在构造器中通过this访问props

函数组件中的props

因为函数组件没有组件实例对象,所以其他两个state和refs是没有的,只有props属性可用,直接在()中接受props对象即可,函数内部就可以结构使用props中的值了

总结:

  • 每个组件都会有props属性
  • 组件标签的所有属性都保存在props
  • 组件内部不能改变外部传进来的props属性值

3.3.3 refs属性

  • 字符串形式的ref(这种方式已过时,不推荐使用,因为效率低)

refs是组件实例对象中的属性,它专门用来收集那些打了ref标签的dom元 素,比方说,组件中的input添加了一个ref=“input1”,那么组件实例中的refs就={input1:input(真实dom)},这样就可以通过this.refs.input1拿到input标签dom了,就不需要想原生js那样通过添加属性id,然后通过document.getElementById(“id”)的方式拿

  • 回调函数形式

直接让ref属性=一个回调函数,为什么这里说是回调函数呢?因为这个函数是你定义的,但不是你调用的,是react在执行render的时候,看到ref属性后跟的是函数,他就会帮你调用了,然后把当前dom标签当成形参传入,所以上述例子这样写,就相当于把当前节点dom赋值给了this.input1,那这个this指的是谁呢?不难理解,这里是箭头函数,本身没有this指向,所以这个this得看外层的,该函数外层是render函数体内,所以this就是组件实例对象,所以ref={c=>this.input1=c}意思就是给组件实例对象添加一个input1,最后要取对应节点dom也直接从this(组件实例中取)

这里我们再来探讨一个小问题,就是这个ref的回调函数会被执行几次的问题?第一次在页面刚进来执行render渲染的时候,react会把当前节点当成参数赋值给组件实例,当组件更新的时候(状态改变时),它又会执行一次render,这个时候,react官方说明了这点,它会执行两次,第一次是将原先的实例属性清空,传入的是null,第二次再把当前节点传如赋值给组件实例的input1属性,这个在一般开发过程中无关紧要,所以大家知道下有这个情况就可以了,当然它也有解决办法:通过将ref的回调函数定义成类的绑定函数的方式,即ref={this.func},func是定义在类中的方法,func=©=>{this.input1=c} ,这种方式就可以解决上述执行两次的问题,一般开发中我们写成回调的形式就可以了

  • createRef

代码解读:createRef()方法是React中的API,它会返回一个容器,存放被ref标记的节点,但该容器是专人专用的,就是一个容器只能存放一个节点;
当react执行到div中第一行时,发现input节点写了一个ref属性,又发线在上面创建了myRef容器,所以它就会把当前的节点存到组件实例的myRef容器中

注意:如果你只创建了一个ref容器,但多个节点使用了同一个ref容器,则最后的会覆盖掉前面的节点,所以,你通过this.ref容器.current拿到的那个节点是最后一个节点

四、 React中的事件处理

  1. 通过onXxxx属性指定事件处理函数(小驼峰形式)
  2. 通过event.target可以得到发生事件的Dom元素
  3. 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。

4.1 高阶函数和函数柯里化


我们写个用到高阶函数和函数柯里化的例子:

...其余代码省略saveFormData=(type)=>{  	return (event)=>{		this.setState({			[type]:event.target.value  		})	}}<form>	<input onChange={ this.saveFormData('username') } />	<input onChange={ this.saveFormData('password') } />	<button>登录</button></form>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

上面代码的saveFormData函数其实就是高阶函数,因为它返回的值是一个函数,而且这个函数就是通过函数柯里化的方式在调用(先是saveFormData函数接收一个参数type,随后返回函数,然后再接收别的参数,然后最终来处理结果(设置state值))

  • 提问1:那为什么要写成这样呢?我直接在函数saveFormData中同时接收两个参数不行吗?
    答:不行,因为你拿不到event,因为这是react帮你处理的

  • 提问2:那还有没有别的方式来实现,不用柯里化处理方式?
    答:有

//将下面函数的调用方式改为这样就可以了,函数接收方式也改下saveFormData=(type,value)=>{	this.setState({		[type]:value	})}<form>	<input onChange={ (event)=>{this.saveFormData('username',event.target.value)} } />	<input onChange={ (event)=>{this.saveFormData('password',event.target.value)} } />	<button>登录</button></form>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

五、 生命周期函数

5.1 老版的生命周期过程:

挂载时:先执行构造器(constructor)=》组件将要挂载(componentWillMount)=》组件挂载渲染(render)=》组件挂载完成(componentDidMount)=》组件销毁(componentWillUnmount)

组件内部状态更新:组件是否应该更新(shouldComponentUpdate)=》组件将要更新(componentWillUpdate)=》组件更新渲染(render)=》组件更新完成(componentDidUpdate)

强制更新:调用this.forceUpdate(),这个api和setState一样都是react自带的,一般这个强制更新很少用,它的执行流程就是比上述的正常更新流程少一步询问是否更新(shouldComponentUpdate)

父组件重新render:调用组件将要接收新props(componentWillReceiveProps)=》组件是否应该更新(shouldComponentUpdate)=》组件将要更新(componentWillUpdate)=》组件更新渲染(render)=》组件更新完成(componentDidUpdate)

注意:上述加粗的函数,只有在父组件状态发生改变了,重新调用render时才会调用子组件的componentWillReceiveProps函数,父组件第一次引用子组件的时时不会调用的

5.2 新版生命周期函数

新版生命周期函数和旧版的差别:新版即将废弃老的3个钩子(componentWillMount、componentWillReceiveProps、componentWillUpdate),新增了2个钩子(getDerivedStateFromProps、getSnapshotBeforeUpdate)

六、 DOM的Diff算法

虚拟DOM中的key的作用:

当状态中的数据发生改变时,react会根据【新数据】生成【新虚拟DOM】,随后react会进行【新虚拟DOM】和【旧虚拟DOM】的diff算法比较,具体的比较规则如下:

  • 若【旧DOM】中找到了与【新DOM】相同的key,则会进一步判断两者的内容是否相同,如果也一样,则直接使用之前的真实DOM,如果内容不一样,则会生成新的真实DOM,替换掉原先的真实DOM
  • 若【旧DOM】中没找到与【新DOM】相同的key,则直接生成新的真实DOM,然后渲染到页面

用index作为key可能引发的问题

  1. 若对数据进行:逆序添加、逆序删除等破坏顺序的操作时会产生不必要的真实DOM更新,造成效率低下
  2. 如果结构中还包含输入类的dom,会产生错误dom更新,出现界面异常

开发中如何选择key

  1. 最好选中标签的唯一标识id、手机号等
  2. 如果只是简单的展示数据,用index也是可以的

七、 脚手架

使用create-react-app(脚手架工具)创建一个初始化项目

1、下载脚手架工具:npm i -g create-react-app

2、创建引用:create-react-app my-app

3、运行应用:cd my-app(进入应用文件夹),npm start(启动应用)

7.1 React脚手架配置代理

  • 方法一

在package.json中追加如下配置

"proxy":"http://localhost:5000"
  • 1

说明:

1、优点:配置简单,前端请求资源可以不加任何前缀
2、缺点:不能配置多个代理(如果请求的不同服务器就不行)
3、工作方式:当请求了自身3000端口不存在的资源时,那么会转发给5000端口(优先会匹配自身的资源,如果自己有就不会请求5000端口了)

  • 方法二

1、第一步:创建代理配置文件

在src下创建配置文件:src/setupProxy.js
  • 1

2、编写代理配置规则

说明:

1、优点:可以配置多个代理,可以灵活控制请求是否走代理
2、缺点:配置繁琐,前端请求资源时必须加前缀

八、 消息订阅-发布机制

背景:

原先react传递数据基本用的是props,而且只能父组件传给子组件,如果子组件要传数据给父组件,只能先父组件传一个函数给子组件,子组件再调用该方法,把数据作为形参传给父组件,那考虑一个事情,兄弟间组件要如何传递数据呢?这就要引出下面这个消息订阅-发布机制

工具库:PubSubJs

下载:npm install pubsub-js --save

使用:

  1. 先引入:import PubSub from “pubsub-js”
  2. 要接收数据方订阅:PubSub.subscribe('消息名',(data)=>{ console.log(data) })
  3. 传递数据方发布:PubSub.publish('消息名',data)

九、React路由

9.1 相关理解

9.1.1.SPA理解

  • 单页面应用(single page web application SPA)
  • 整个页面只有一个完整的页面(html文件)
  • 点击页面的链接不会刷新页面,只会做页面的局部更新
  • 数据都需要通过ajax请求获取,并在前端异步展示

9.1.2.路由的理解

1、 什么是路由?

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

2、 路由分类

  • 后端路由

    a )理解:后端路由的key还是路径,只不过value是上述说的function,这个在学习node和Express的时候应该看到过,如下图

    b) 注册路由:router.get(path,function(req,res){…})
    c) 工作过程:当node接收到一个请求时,会根据请求路径去匹配对应的路由,然后调用对应路由中的函数来处理请求,返回响应数据

  • 前端路由

    a) 浏览器端路由,value是对应组件(component),用于展示页面内容
    b) 注册路由:<Route path='/test',component={Test}>
    c) 工作过程:当浏览器path变为/test时,当前路由组件就会变成Test组件

9.2 react-router-dom

9.2.1 理解

  • 它是react的一个插件库
  • 专门用来实现一个SPA单页面应用
  • 基于react的项目基本都用它

9.2.2 常用API

1、内置组件

  • <BrowserRouter>
  • <HashRouter>
  • <Route>
  • <Redirect>
  • <Link>
  • <NavLink>
  • <Switch>

2、知识点

  • 路由的基本使用

  • 路由组件和一般组件

  • NavLink的使用

  • Switch的使用

  • 路由的模糊匹配和精准匹配

  • Redirect的使用

  • 嵌套路由

  • 向路由组件传递参数

  • 路由跳转的两种模式(push、replace)

默认开启的是push模式,push模式就是说每次的点击跳转改变路径,都是往浏览器历史记录的栈中不断追加一条记录,然后你点回退按钮时,它会指向当前栈顶记录的前一条,replcae模式就是说替换掉当前的那条记录,然后你点回退的时候,就不会显示上次被替换掉的那条记录了,只会显示上上条记录,那要怎么设置为replace模式呢?直接在<Link replace to='XXX'>标签上添加一个replace属性即可

  • 编程式路由导航(不借助link或者navLink这种手动点触发路由跳转)

就是借用history对象的api来操作路由的跳转、前进、后退

  • withRouter的使用

作用:它就是专门解决在一般组件中想要使用路由组件的那几个API的这个问题的,它接收一个一般组件,然后调用后,该一般组件身上也有了路由组件的history、match等属性

如何使用:
1、先引入import { withRouter} from "react-router-dom"
2、定义一般组件class XX extends ...
3、export default withRouter( XX )

  • BrowserRouter和HashRouter的区别

10、redux

10.1 redux理解

10.1.1 redux是什么?

  1. 它是专门做状态管理的js库,不是react插件库
  2. 它可以用在angular、vue、react等项目中,但与react配合用到最多
  3. 作用:集中式管理react应用中多个组件共享的状态

10.1.2 什么情况下需要使用它

  1. 某个组件的状态需要让其他组件也能拿到
  2. 一个组件需要改变另一个组件的状态(通信)
  3. 总体原则:能不用就不用,如果不用比较吃力,就可以使用

redux的工作流程

11、react-redux

原先redux是独立公司创建的,后来react公司发现开发者都这么喜欢在react项目中使用redux,所以就自己开发了一个react的插件叫react-redux

11.1、react-redux模型图

11.2、react-redux基本使用

11.2、纯函数

11.3、react-redux开发者工具

  1. 打开chrome网上商店,下载开发者工具Redux DevTools
  2. 下载完后右上方的插件图标还是不会亮的,因为它还识别不了你写的redux,所以还需要下载一个库(redux-devtools-extension)
  3. 然后再你的store文件中引入该库文件import {composeWithDevTools} from redux-devtools-extension
  4. 然后再createStore()的第二个参数位置调用composeWithDevTools(),将之前放在这个位置的中间件传到该方法中
    export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))

12、项目打包运行

在react脚手架中通过npm run start 来运行启动项目并打开页面,打包生成静态文件就要用到另一个命令(npm run build),它会生成一个build文件夹,一般这个生成的静态文件都是放到服务器上去运行的,那么问题来了,服务器要怎么搭建呢?

方法一:用node+express可以搭建一个简单的服务器
方法二:需要用到一个库serve,使用前需要先下载npm i serve -S,然后直接在对应文件夹中执行serve即可,比方在这里,当前文件路径是项目根目录,直接serve build即可,就可以开启一个5000端口的服务器了

13、Hooks

13.1、React Hook /Hooks是什么?

1、Hook是React 16.8新推出的新特性/新语法
2、可以让你在函数式组件中使用state或其他特性

13.2、三个常用Hook

1、React.useState()
2、React.useEffect()
3、React.useRef()

13.3、useState


Demo:

import React,{useState} from 'react';export default ()=>{  //useState()中接收的是state的默认值,前面是数组解构,第一个是state变量,第二个是改变state的方法,类似于setState()  const [count,setCount] =useState( 0 )  	render(  		<div>{count}</div>  		<button onClick={()=>{setCount(count+1)}}>点我+1</button>  	)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这里思考个问题,当你点击按钮+1时,状态改变的时候,整个函数组件就会执行,所以第四行也自然会执行,那它的状态不就又变成0了吗?还能正常+1吗?

答案:是可以正常+1,为什么呢?因为这行代码底层做了处理,当状态改变重新调用整个函数组件时,这句话是会执行,但它不会去覆盖count值,所以count值还是会正常+1

13.4、useEffect

总结:这个钩子函数相当于类组件三个钩子函数的集合,当你想用做componentDIdMount时,可以在第二个参数中加上[],表示谁都不监听,只会在第一次挂载时调用,这就相当于didMount函数了,如果你想当componentDidUpdate函数用,那么你可以在第二个参数加上你要监听更新的state值,注意是数组,如果你要当componentWillUnmount函数,则在useEffect()接收的第一个函数中返回一个函数,这个返回的函数就相当于willUnMount

13.5、useRef

14、React扩展知识

14.1、setState的两种写法

Demo:

//这里我们先统一不考虑第二个参数回调对象式写法:const {count} =this.state;this.setState({ count:count+1})    //setState()方法接收一个对象函数式写法:this.setState((state,props)=>{    //函数式写法可以接收老的state和props数据	return {count:1}})简写:this.setState(state=>({count+state}))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

14.2、lazyload(懒加载)

这里我们要讲的懒加载主要是针对路由组件的懒加载,就是你点击路由导航菜单,加载对应组件的时候懒加载,具体来看下面code。。。

//原先的路由组件引入:import Demo1 from "./Demo1"import Demo2 from "./Demo2"<Route path='/demo1',component={Demo1}/><Route path='/demo2',component={Demo2}/>//现在使用lazyload:import React,{component,lazy} from "react    // 需要用到react中的lazy函数// 引入路由组件方式通过调用lazy(),然后接收一个函数的方式,import 引入文件也可以通过函数调用的方式const Demo1 = lazy(()=>{import('./Demo1')})  const Demo2 = lazy(()=>{import('./Demo2')})  //路由配置那边也要改动,用Suspense标签包裹下,再传一个fallback属性,接收一个组件,你可以自定义一个加载过程中的简单组件,再资源没回来之前会显示这个传入的简单加载组件,就是为了再网速慢得情况下,页面不至于白屏,提高用户体验<Suspense fallback={组件}>	<Route path='/demo1',component={Demo1}/>	<Route path='/demo2',component={Demo2}/></Suspense>**注意:**这里引入得加载组件必须通过直接引入的方式import Loading from "./Loading"`
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

14.3、Fragment标签

简单一句话概括:这个标签就是用在有时页面结构层级太多,而且有些都是语法要求,实际没意义的结构层级(return()中的根节点就是这个情况),这时你就可以用Fragment标签,当然<></>在一般情况下和Fragment标签作用相同,当时有一点不一样,就是Fragment标签能接收一个key属性,而<></>什么属性都不能接收

14.4、Context

理解:这里说的Context其实就是类组件中实例对象中的一个属性,它和state、props、ref是同一级的;
作用:它可以解决多层组件之间,祖先组件要往后代组件传递数据的情况,不用再一层一层的props传
使用原理: 举个例子,要把父组件中state的值传递给孙子组件,那么在父组件的全局位置创建一个容器对象,然后用这个容器对象的Provider标签包裹父组件,同时传value={state数据},注意,这里的value字段名不能改,只能是value,然后孙子组件可以用下面的两种方式去接收数据

14.5、PureComponent(纯组件)

具体的使用:就是原先extends Component=》extends PureComponent 即可

14.6、错误边界

所谓的错误边界就是说,在实际开发过程中,组件复用是很正常的,但你很难避免调用的子组件出现错误(语法错误,或者是因为数据格式不对导致的报错,你不可能兼容到各个位置),如果没有错误边界,当子组件出现问题的时候,整个页面就都会挂掉,所以为了用户体验,让错误不影响整个页面,所以要用这个错误边界,注意:这个错误边界时要在父组件中进行处理的

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发