React18.x-学习笔记
react核⼼库
react-development.js
react-dom-development.js
bebal.min.js
jsx语法规则
定义虚拟Dom时,不要写引号。
标签中混⼊js表达式要⽤{}。
样式的类名指定不要⽤class 要⽤className
内联样式,要⽤style={对象}—> style={{key:value}}的形式去写
只能有⼀个根标签
标签必须闭合或者单标签⾃闭合
标签⾸字母
1. 若⼩写字母开头,则将该标签转为html中同名元素,若HTML中⽆该标签对应的同名元素,则报错。
2. 若⼤写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
灵魂拷问
在复杂组件中 constructor构造函数执⾏⼏次?
答:有⼏个复杂组件的实例就执⾏⼏次,只有⼀个组件实例则执⾏⼀次
在复杂组件中render函数执⾏⼏次?
答:当状态发⽣改变时则重新执⾏render函数 1+n次。 1代表初始化时执⾏。n代表状态(state)更新了⼏次。组件三⼤特性
1.状态(state).
2.props.
⾼阶函数
定义:什么是⾼阶函数?
如果⼀个函数符合下⾯2个规范中的任何⼀个,那该函数就是⾼阶函数。
若A函数,接受的参数是⼀个函数,那么A就可以称之为⾼阶函数。
若A函数,调⽤的返回值依然是⼀个函数,那么A就可以称之为⾼阶函数。
常见的⾼阶函数有:Promise setTimeout arr.map() duce() arr.filter() arr.some() arr.sort() ….
函数柯⾥化:通过函数调⽤继续返回函数的⽅式,实现多次接受参数最后统⼀处理的函数编码形式。
⽣命周期(重要)
在React17.0.0版本之前的⽣命周期钩⼦(旧版本)
执⾏顺序
constructor
componentDidMount 组件挂载前执⾏的钩⼦
render 函数在中间执⾏
componentDidMount 组件挂载完成后执⾏的钩⼦ //常⽤⽐如:开启定时器,发送⽹络请求,订阅消息
componentWillUnmount 组件卸载前执⾏的钩⼦ //常⽤⽐如:关闭定时器,取消订阅消息
更新组件执⾏的⽣命周期钩⼦
shouldComponentUpdate ⽤于控制是否更新状态的钩⼦
不写默认返回true 在组件中写⼊这个钩⼦必须要返回值
componentWillUpdate 组件更新前的钩⼦即将废除
render 函数执⾏
componentDidUpdate 组件更新完毕执⾏钩⼦
新版本⽣命周期
即将废除3
新增钩⼦:getDerivedStateFromProps
getSnapshotBeforeUpdate
虚拟DOM的Diffing算法
在循环列表项中加⼊Key值利于提⾼Diff算法的效率
diff算法⽐较新旧dom 然后根据key来判断旧的虚拟Dom节点是否可以复⽤。
在循环列表项中如果要打乱顺序插⼊列表项,不要使⽤数组的索引值(index)来作为key使⽤。这样会发⽣严重后果且跟新效率低下。订阅消息与发布消息 pubsub-js
安装订阅发布消息库 pubsub-js
yarn add pubsub-js
在组件中引⼊pubsub库
import PubSub from 'pubsub-js'
在组件中发布消息。
PubSub.publish(‘发布的消息名称’,payload(载荷/数据))
在组件中订阅消息,⼀般在组件挂载完成的时候订阅,在componentDidMount钩⼦中订阅
console.log(mesName,data)// 事件名称,收到发布消息的载荷
})
在组件卸载前取消订阅 componentWillUnmount钩⼦中取消订阅
componentWillUnmount(){
PubSub.ken);
}
react 路由
核⼼库:react-router-dom
路由组件的使⽤
import {withRouter,HashRouter,BrowserRouter,Link,NavLink,Switch,Redirect,Route} from 'react-router-dom'
各组件的功能
HashRouter组件,使⽤Hash模式的路由器,(⽤的不多)
BrowserRouter组件,浏览器使⽤的路由器,使⽤history模式进⾏路由切换,⼀般在SPA应⽤上包裹在App组件上。
Link组件,进⾏路由导航链接的组件
NavLink组件,进⾏路由导航链接的组件多⼀个⾼亮效果,默认active类名。
可以通过activename来更改选中时的类名
Switch组件,Switch包裹在路由组件中<Switch> <Route/></Switch>中.
⽤于对路由匹配的限制,匹配到了就不往下匹配了。就终⽌路由匹配
Redirect组件,重定向组件。⼀般⽤来兜底的组件。
在路由组件什么也没匹配到的情况下,Redirect重定向到指定路径中。
Route组件路由组件
将⼀般组件变成路由组件,同时可以指定匹配的路径。路由组件中还会有this.props.history的API
withRouter ⽅法,
将⼀般组件变成路由组件的函数,同时拥有historyAPI
使⽤⽅式: withRouter(componentName)
返回⼀个新组件,导出即可。
路由的模糊匹配和嵌套路由。
默认路由采⽤的是,模糊匹配。如果想要严格匹配加上 exact
嵌套路由
1.注册⼦路由时要写上⽗路由的path值
2.路由的匹配是按照注册路由的顺序进⾏的
路由传递参数(重要)
1.params参数
路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
接收参数:this.props.match.params
2.search参数
路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
注册路由(⽆需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.search
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
3.state参数
路由链接(携带参数):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>注册路由(⽆需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
接收参数:this.props.location.state
备注:刷新也可以保留住参数
redux要点
1. redux理解
2. redux相关API
3. redux核⼼概念(3个)
4. redux⼯作流程
5. 使⽤redux及相关库编码
1. redux理解
什么?: redux是专门做状态管理的独⽴第3⽅库, 不是react插件
作⽤?: 对应⽤中状态进⾏集中式的管理(写/读)
开发: 与react-redux, redux-thunk等插件配合使⽤
2. redux相关API
redux中包含: createStore(), applyMiddleware(), combineReducers()
store对象: getState(), dispatch(), subscribe()
react-redux: <Provider>, connect()()
3. redux核⼼概念(3个)
action:
默认是对象(同步action), {type: 'xxx', data: value}, 需要通过对应的actionCreator产⽣,
它的值也可以是函数(异步action), 需要引⼊redux-thunk才可以
reducer
根据⽼的state和指定的action, 返回⼀个新的state
不能修改⽼的state
store
redux最核⼼的管理对象
内部管理着: state和reducer
提供⽅法: getState(), dispatch(action), subscribe(listener)
4. redux⼯作流程
5. 使⽤redux及相关库编码
需要引⼊的库:
redux
react-redux
redux-thunk
redux-devtools-extension(这个只在开发时需要)
redux⽂件夹:
action-types.js
actions.js
reducers.js
store.js
组件分2类:
ui组件(components): 不使⽤redux相关PAI
容器组件(containers): 使⽤redux相关API
6.React-扩展
setState
setState更新状态的2种写法
(1). setState(stateChange, [callback])------对象式的setState
1.stateChange为状态改变对象(该对象可以体现出状态的更改)
2.callback是可选的回调函数, 它在状态更新完毕、界⾯也更新后(render调⽤后)才被调⽤
(2). setState(updater, [callback])------函数式的setState
1.updater为返回stateChange对象的函数。
2.updater可以接收到state和props。
4.callback是可选的回调函数, 它在状态更新、界⾯也更新后(render调⽤后)才被调⽤。
总结:
1.对象式的setState是函数式的setState的简写⽅式(语法糖)
2.使⽤原则:
(1).如果新状态不依赖于原状态 ===> 使⽤对象⽅式
(2).如果新状态依赖于原状态 ===> 使⽤函数⽅式
react组件之间通信(3).如果需要在setState()执⾏后获取最新的状态数据, 要在第⼆个callback函数中读取
setState()的异步与同步
1). setState()更新状态是异步还是同步的?
a. 执⾏setState()的位置?
在react控制的回调函数中: ⽣命周期勾⼦ / react事件监听回调
⾮react控制的异步回调函数中: 定时器回调 / 原⽣事件监听回调 / promise回调 /...
b. 异步 OR 同步?
react相关回调中: 异步
其它异步回调中: 同步
2). 关于异步的setState()
a. 多次调⽤, 如何处理?
setState({}): 合并更新⼀次状态, 只调⽤⼀次render()更新界⾯ ---状态更新和界⾯更新都合并了
setState(fn): 更新多次状态, 但只调⽤⼀次render()更新界⾯ ---状态更新没有合并, 但界⾯更新合并了
b. 如何得到异步更新后的状态数据?
在setState()的callback回调函数中
2. lazyLoad
路由组件的lazyLoad
//1.通过React的lazy函数配合import()函数动态加载路由组件 ===> 路由组件代码会被分开打包
const Login = lazy(()=>import('@/pages/Login'))
//2.通过<Suspense>指定在加载得到路由打包⽂件前显⽰⼀个⾃定义loading界⾯
<Suspense fallback={<h1&</h1>}>
<Switch>
<Route path="/xxx" component={Xxxx}/>
<Redirect to="/login"/>
</Switch>
</Suspense>
3. Hooks
1. React Hook/Hooks是什么?
(1). Hook是React 16.8.0版本增加的新特性/新语法
(2). 可以让你在函数组件中使⽤ state 以及其他的 React 特性
2. 三个常⽤的Hook
(1). State Hook: React.useState()
(2). Effect Hook: React.useEffect()
(3). Ref Hook: React.useRef()
3. State Hook
(1). State Hook让函数组件也可以有state状态, 并进⾏状态数据的读写操作
(2). 语法: const [xxx, setXxx] = React.useState(initValue)
(3). useState()说明:
参数: 第⼀次初始化指定的值在内部作缓存
返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
(4). setXxx()2种写法:
setXxx(newValue): 参数为⾮函数值, 直接指定新的状态值, 内部⽤其覆盖原来的状态值
setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部⽤其覆盖原来的状态值4. Effect Hook
(1). Effect Hook 可以让你在函数组件中执⾏副作⽤操作(⽤于模拟类组件中的⽣命周期钩⼦)
(2). React中的副作⽤操作:
发ajax请求数据获取
设置订阅 / 启动定时器
⼿动更改真实DOM
(3). 语法和说明:
useEffect(() => {
// 在此可以执⾏任何带副作⽤操作
return () => { // 在组件卸载前执⾏
// 在此做⼀些收尾⼯作, ⽐如清除定时器/取消订阅等
}
}, [stateValue]) // 如果指定的是[], 回调函数只会在第⼀次render()后执⾏
(4). 可以把 useEffect Hook 看做如下三个函数的组合
componentDidMount()
componentDidUpdate()
componentWillUnmount()
5. Ref Hook
(1). Ref Hook可以在函数组件中存储/查组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作⽤:保存标签对象,功能与ateRef()⼀样
4. Fragment使⽤
<Fragment><Fragment>
<></>
作⽤
可以不⽤必须有⼀个真实的DOM根标签了
## 5. Context ### 理解 > ⼀种组件间通信⽅式, 常⽤于【祖组件】与【后代组件】间通信 ### 使⽤ ```js 1) 创建Context容器对象: const XxxContext = ateContext()
2. 渲染⼦组时,外⾯包裹xxxContext.Provider, 通过value属性给后代组件传递数据:
<xxxContext.Provider value={数据}>
⼦组件
</xxxContext.Provider>
3. 后代组件读取数据:
//第⼀种⽅式:仅适⽤于类组件
static contextType = xxxContext // 声明接收context
//第⼆种⽅式: 函数组件与类组件都可以
<xxxContext.Consumer>
{
value => ( // value就是context中的value数据
要显⽰的内容
)
}
</xxxContext.Consumer>
### 注意
在应⽤开发中⼀般不⽤context, ⼀般都⽤它的封装react插件
<hr/>
## 6. 组件优化 Component与PureComponent
```js
1). Component存在的问题?
a. ⽗组件重新render(), 当前组件也会重新执⾏render(), 即使没有任何变化
b. 当前组件setState(), 重新执⾏render(), 即使state没有任何变化
2). 解决Component存在的问题
a. 原因: 组件的shouldcomponentUpdate()默认返回true, 即使数据没有变化render()都会重新执⾏
b. 办法1: 重写shouldComponentUpdate(), 判断如果数据有变化返回true, 否则返回false
c. 办法2: 使⽤PureComponent代替Component
d. 说明: ⼀般都使⽤PureComponent来优化组件性能
3). PureComponent的基本原理
a. 重写实现shouldComponentUpdate()
b. 对组件的新/旧state和props中的数据进⾏浅⽐较, 如果都没有变化, 返回false, 否则返回true
c. ⼀旦componentShouldUpdate()返回false不再执⾏⽤于更新的render()
4). ⾯试题:
组件的哪个⽣命周期勾⼦能实现组件优化?
PureComponent的原理?
区别Component与PureComponent?
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论