目录
10.BrowserRouter与HashRouter的区别
1.hello_react
2.jsx的语法规则
3.React中定义组件
函数式组件
类式组件
构造器可写可不写。
render函数一共执行1+n次,页面初始化的时候执行第一次,每次更新页面再执行一次。
组件实例三大属性之state
state是组件对象最重要的属性,值是对象(可以包含多个key-value组合)
组件被称为状态机,state就是状态,通过更新组件的state来更新页面对应的部分(类比Vue的data)。
state中的数据不能直接修改,要通过setState才能修改(类比小程序的setData)。
组件实例三大属性之props
每个组件都会有props属性,保存从组件外传进来的属性。
对props进行限制(非简写形式)
首先要引入prop-types.js文件。
写在类外。
对props进行限制(简写形式)
直接写在类里,像静态变量一样。
组件实例三大属性之refs
字符串形式的refs(不被推荐,已经过时)
控制台中输出的Demo组件实例上有refs这个属性,其中包含的是一组一组的键值对。key是ref的值,value是ref标记的结点。
String类型的refs效率不高,在未来版本可能被移除。
回调形式的ref
ref回调函数中的形参就是ref标记的结点。
createRef(官方最推荐)
myRef由一个键值对组成,键名为current,键值则为DOM结点。
myRef只能标记一个DOM元素,如果再用它标记另外一个结点,则会覆盖之前的结点。
生命周期(旧)
页面初始化时生命周期钩子的执行顺序如下:
页面正常更新,指通过setState改变state中数据时生命周期钩子的执行顺序如下:
页面强制更新,指通过forceuodate让页面发生更新,但并不在乎是否真的修改数据:
生命周期(新)
在新版本的生命周期中,
componentWillMount、
componentUpdate、
componentWillReceiveProps
都被不推荐使用,如果使用会触发警告,添加UNSAFE_前缀可消除警告。这里的“unsafe”不是指安全性,而是表示使用这些生命周期的代码在React以后的版本中可能出现bug,尤其是启用异步渲染之后。
getDerivedStateFromProps
getDerivedStateFromProps会在调用render方法之前调用,并且在初挂载以及后续更新时都会被调用。它返回一个对象来更新state,如果返回null则不更新任何内容。
此方法适用于罕见的用例,及state的值在任何时候都取决于props。
了解即可,使用频率极小。
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate()在最近一次渲染输出(提交到DOM结点)之前调用。它使得组件能在发生更改前从DOM中获取一些信息。此生命周期的任何返回值将作为参数传递给componentDidUpdate()。
顾名思义,该生命周期方法在更新前给组件拍了个“快照”,保留了组件更新前的一些信息(在更新后依然要用到)。
getSnapshotBeforeUpdate(prveProps,prevState)中的两个参数分别保存了更新前的props和state。
componentDidUpdate(preProps,preState,snapshotValue)中的前两个分别参数保存了组件更新前的props和state,第三个参数保存的是getSnapshotBeforeUpdate(prveProps,prevState)返回的值。
常用三大生命周期:
- render:初始化渲染或更新渲染调用。
- componentDidMount:开启监听, 发送ajax请求。
- componentWillUnmount:做一些收尾工作, 如: 清理定时器。
Key的作用(Vue、React都适用)
虚拟DOM中key的作用:
1.简单的说:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。
2.详细的说:当状态中的数据发生变化时,react会根据【新数据】生成新的虚拟DOM,随后React进行【新虚拟DOM】与【旧虚拟DOM】的diffing比较,比较规则如下:
a.旧虚拟DOM中找到了与新虚拟DOM相同的key:
①若虚拟DOM中内容没变,直接使用之前的真实DOM。
②若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
b.旧虚拟DOM中未找到与新虚拟DOM相同的key。
根据数据创建新的真实DOM,随后渲染到页面。
用index作为key可能引发的问题:
1.若对数据进行逆序添加、逆序删除等破坏顺序操作:
会产生没必要的真实DOM更新,界面效果虽没问题,但效率低
2.如果结构中包括输入类的DOM,则会产生错误的DOM更新
3.如果仅用于渲染列表,使用index作为key是没问题的,但尽量避免。
开发中如何选择key?
1.最好使用每一条数据的唯一标识作为key,比如id、手机号、学号、身份证号等唯一值。
2.如果只是简单的展示数据,可以用index。
React脚手架
1.1 react脚手架
- xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
- 包含了所有需要的配置(语法检查、jsx编译、devServer…)
- 下载好了所有相关的依赖
- 可以直接运行一个简单效果
- react提供了一个用于创建react项目的脚手架库: create-react-app
- 项目的整体技术架构为: react + webpack + es6 + eslint
- 使用脚手架开发的项目的特点: 模块化, 组件化, 工程化
1.2 创建项目并启动
第一步,全局安装:npm i -g create-react-app
第二步,切换到想创项目的目录,使用命令:create-react-app hello-react/npx create-react-app my-app
第三步,进入项目文件夹:cd hello-react
第四步,启动项目:npm start
1.3 react脚手架项目结构
消息订阅与发布pubsub
pubsub适用于任意组件之间进行通信。
首先,引入模块:
在订阅消息的组件里配置如下:
subscribe(a,b):
a:消息名;
b:回调函数,该函数有两个参数,分别是消息名(可用占位符_代替)和传递的数据。
在发布消息的组件配置里如下:
最后在componentWillunmount中取消订阅。
fetch
......
路由
1.路由的基本使用
BrowserRouter(HashRouter)就是路由器,管理所有的路由。
to和path一一对应。
2.路由组件与一般组件
3.navLink与封装navLink
4.路由的严格匹配与模糊匹配![](https://img-blog.csdnimg.cn/d0e605f0954d4ce6815eb474a1a0164f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65YWJNjQw,size_20,color_FFFFFF,t_70,g_se,x_16)
5.Redirect的使用
Redirect起到一个兜底的作用。
6.嵌套路由
7.向路由传递参数
7.1 params参数![](https://img-blog.csdnimg.cn/2e118d3ccc9b4f35a2f404159538689c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65YWJNjQw,size_20,color_FFFFFF,t_70,g_se,x_16)
注意:传参时使用了大括号+模板字符串的语法
7.2 search参数![](https://img-blog.csdnimg.cn/bb9ee2b097794cfb969d5db5bb35f7bc.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65YWJNjQw,size_20,color_FFFFFF,t_70,g_se,x_16)
search参数类似Vue中的query,"?"隔开路径和参数,"&"连接参数。
新版本qs已弃用,需安装query-string插件:npm i -save-dev query-string
然后在页面引入:import QueryString from 'query-string
7.3 state参数![](https://img-blog.csdnimg.cn/6fe7380c7fa34c4490426c99f9db8cf5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65YWJNjQw,size_20,color_FFFFFF,t_70,g_se,x_16)
此state不是组件的状态state,而是路由独有的一个属性。
使用state传参时,to要写成一个对象。第一对{}代表括号内的是jsx表达式,第二对{}代表一个对象。
8.编程式路由导航
与Vue的编程式路由导航类似。
9.withRouter
1.withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
2.withRouter的返回值是一个新组件
引入withRouter:
暴露出被加工成路由组件的一般组件:
10.BrowserRouter与HashRouter的区别
11.switch
redux
1.redux是什么
- redux是一个专门用于做状态管理的JS库(不是react插件库)。
- 它可以用在react, angular, vue等项目中, 但基本与react配合使用。
- 作用: 集中式管理react应用中多个组件共享的状态。
2.什么时候使用redux
- 某个组件的状态,需要让其他组件可以随时拿到(共享)。
- 一个组件需要改变另一个组件的状态(通信)。
- 总体原则:能不用就不用, 如果不用比较吃力才考虑使用。
3.redux工作流程
4.redux的三个核心概念
4.1 action
- 动作的对象
- 包含2个属性
- type:标识属性, 值为字符串, 唯一, 必要属性
- data:数据属性, 值类型任意, 可选属性
- 例子:{ type: 'ADD_STUDENT',data:{name: 'tom',age:18} }
4.2 reducer
- 用于初始化状态、加工状态。
- 加工时,根据旧的state和action, 产生新的state的纯函数。
4.3 store
- 将state、action、reducer联系在一起的对象
- 如何得到此对象?
- import {createStore} from 'redux'
- const store = createStore(reducer)
- import reducer from './reducers'
- 此对象的功能?
- getState(): 得到state
- subscribe(listener): 注册监听, 当产生了新的state时, 自动调用
- dispatch(action): 分发action, 触发reducer调用, 产生新的state
react-redux
1.react-redux是什么
- 一个react插件库
- 专门用来简化react应用中使用redux
2.react-Redux将所有组件分成两大类
- UI组件
- 只负责 UI 的呈现,不带有任何业务逻辑
- 通过props接收数据(一般数据和函数)
- 不使用任何 Redux 的 API
- 一般保存在components文件夹下
- 容器组件
- 负责管理数据和业务逻辑,不负责UI的呈现
- 使用 Redux 的 API
- 一般保存在containers文件夹下
- UI组件存放在components文件夹中,容器组件存放在container文件夹中。
容器组件的编写:
容器组件通过mapStateToProps方法向UI组件传递state
容器组件通过mapDispatchToProps方法向UI组件传递操作状态的方法
在App.jsx文件中引入的是容器组件,而且要给容器组件通过props传递store
使用provider就可以避免手动给组件传递props
react扩展
1.setState更新状态的两种写法![](https://img-blog.csdnimg.cn/3b603071e4a445f3bc905729b9c24717.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65YWJNjQw,size_20,color_FFFFFF,t_70,g_se,x_16)
callback是可以省略的。
2. lazyLoad
3.Hooks
(1). Hook是React 16.8.0版本增加的新特性/新语法
(2). 可以让你在函数组件中使用 state 以及其他的 React 特性
(3). 为什么要是有Hooks呢,因为函数式组件没有自己的this
3.1 三个常用的Hook
3.2 State Hook![](https://img-blog.csdnimg.cn/fd2c930abcb547119ec8ee34a9d7e6af.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65YWJNjQw,size_20,color_FFFFFF,t_70,g_se,x_16)
3.3 Effect Hook![](https://img-blog.csdnimg.cn/17460fe749c843afbbf4c9b6d8dd37c6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65YWJNjQw,size_20,color_FFFFFF,t_70,g_se,x_16)
上图两个生命周期的作用同下面的Effect Hooks
3.4 Ref Hook![](https://img-blog.csdnimg.cn/9a089ac18ad949a3848055ca386b2d0e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Li65YWJNjQw,size_20,color_FFFFFF,t_70,g_se,x_16)
4. content
一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信,类似vue里的provide与inject
注意:在应用开发中一般不用context, 一般都用它的封装react插件
5. 组件优化
6. render props
7. 错误边界
8. 组件间通信方式总结
ReactRouters6
1. 概述
2.Component
2.1.<BrowserRouter>
-
说明:
<BrowserRouter>
用于包裹整个应用。
2.2. <HashRouter>
-
说明:作用与
<BrowserRouter>
一样,但<HashRouter>
修改的是地址栏的hash值。 -
备注:6.x版本中
<HashRouter>
、<BrowserRouter>
的用法与 5.x 相同。
2.3. <Routes/> 与 <Route/>
-
v6版本中移出了先前的
<Switch>
,引入了新的替代者:<Routes>
。 -
<Routes>
和<Route>
要配合使用,且必须要用<Routes>
包裹<Route>
。 -
<Route>
相当于一个 if 语句,如果其路径与当前 URL 匹配,则呈现其对应的组件。 -
<Route caseSensitive>
属性用于指定:匹配时是否区分大小写(默认为 false)。 -
当URL发生变化时,
<Routes>
都会查看其所有子<Route>
元素以找到最佳匹配并呈现组件 。 -
<Route>
也可以嵌套使用,且可配合useRoutes()
配置 “路由表” ,但需要通过<Outlet>
组件来渲染其子路由。
旧版本注册路由的方式:
2.4. <Navigate>
-
作用:只要
<Navigate>
组件被渲染,就会修改路径,切换视图。 -
replace
属性用于控制跳转模式(push 或 replace,默认是push)。
2.5. <Outlet/>
-
当
<Route>
产生嵌套时,渲染其对应的后续子路由。 -
新旧对比如下:
新:
旧:
3. Hooks
3.1. useRoutes()
作用:根据路由表,动态创建<Routes>
和<Route>
。
//路由表配置:src/routes/index.js
在children里配置子组件时,可以不加“/”,因为父组件已经有了,这点也和vue里配置子组件的规则一样。
//App.jsx
很像Vue里router的配置:
3.2. useNavigate()
-
作用:返回一个函数用来实现编程式导航。
-
navigat的两个参数:
-
路径(子路由不加/,可以加search参数或params参数)
-
配置对象:跳转方式、state参数
-
3.非路由组件想要实现路由跳转的话,直接使用useNavigate()
3.3. useParams()
作用:回当前匹配路由的params
参数,类似于5.x中的match.params
。
切记:使用prams参数时要占位!!
3.4. useSearchParams()
-
作用:用于读取和修改当前位置的 URL 中的查询字符串。
-
返回一个包含两个值的数组,内容分别为:当前的search参数、更新search的函数。
-
使用search.get(属性名)获得接收到的search参数。
-
使用setSearch更新search参数时,必须传入一个search参数的字符串形式。
3.5. useLocation()
-
作用:获取当前 location 信息,对标5.x中的路由组件的
location
属性。
2.通过useLocation可以获得search参数和state参数
3.6. useMatch()
作用:返回当前匹配信息,对标5.x中的路由组件的match
属性。
3.7. useInRouterContext()
作用:如果组件在 <Router>
的上下文中呈现,则 useInRouterContext
钩子返回 true,否则返回 false。
解释:<App/>被包裹在<BrowserRouter>(<HashRouter>)中,那么App包括它的所有子组件都处在路由的上下文环境中。
3.8. useNavigationType()
-
作用:返回当前的导航类型(用户是如何来到当前页面的)。
-
返回值:
POP
、PUSH
、REPLACE
。 -
备注:
POP
是指在浏览器中直接打开了这个路由组件(刷新页面)。
3.9. useOutlet()
-
作用:用来呈现当前组件中渲染的嵌套路由。
3.10. useResolvedPath()
作用:给定一个 URL值,解析其中的:path、search、hash值。