1. React特点
视图层框架 组件系统 单向数据流 前后端分离
2. React Filber
分片,把每一个耗时长的任务分成很多小片,每一小片的运行时间很短.
3. Component
任何元素都可以看作一个组件
4. React 脚手架
create-react-app 底层Webpack
5. create-react-app的使用
1.全局安装 cnpm i create-react-app -g
2.创建脚手架项目 npx create-react-app demo
3.启动项目 yarn start
4.webpack配置文件 node_module/react-script/config/webpack.config.js
5.抽离webpack配置文件 yarn eject
6.create-react-app 配置less模块化
https://blog.csdn.net/harry_yaya/article/details/108453744
7.React的两种数据形式
state [状态] props[属性]
1.props
1>类组件
1.外部传入 this.props接受
2.内部定义 static defaultProps={}
2>函数组件
1.外部传入 {aa} 在参数中解构
3>props校验 prop-types 校验外部传入
Hello.propTypes = {
aa:PropTypes.string
}
2.state [自己定义,自己修改]
1>类组件
1.state = {count:0}
2.constructor(props){
super(props) //this.props = props
this.state = {count:0}
}
2>函数组件
1.useState [Hooks]
const [count] = useState(0)
8.事件绑定形式
1.类组件
onClick={this.handle} const handle = ()=>{console.log(1)}
2.函数组件
onClick={handle} const handle = ()=>{console.log(1)}
3.函数传参需要使用箭头函数包裹
onClick={ () => { handle(val) } } const handle = ()=>{console.log(1)}
9.setState修改状态
1.类组件
this.setState({
count:this.count++
})
this.setState(({count}))=>{
return {
count:count
}
})
setState两个回调函数,第一个回调函数修改state数据,第二个回调函数可以拿到更新后得state值
2.函数组件
const [ count,setCount ] = useState(0)
handle = ()=>{
setCount(1) //赋值一次
}
handle = ()=>{
setCount( preCount=>preCount+1 ) //回调函数
}
短时间,多次执行多个setState,React会进行合并 {合并列 Object.assign 队列}
10.数据渲染
1.数据展示 {} dangerousSetInnerHTML = {{__html:xml}}
2.条件渲染 { flag ? '真' : '假' } //可以是标签
3.列表渲染 <ul>{ arr.map( item => <li key={index} >{item}</li> )}</ul> 需要有Key值
11.组件通信
1.父子组件 【父组件定义状态,子组件接受】
2.子父组件 【子组件定义状态,父组件给子组件船事件,子组件调用事件传参,父组件接收参数】
3.非父子组件 类组件【1.父组件定义方法传给其中一个组件2.其他一个组件使用ref ref={ el => this.hello = el } this.hello.方法名】
4.跨组件 【createContext 创建上下文 moneyContext.Provider value={money} 孙子组件:static contextType = moneyContext this.context】
12.生命周期(类组件) 父组件状态更改会引起子组件的重新渲染render
1.初始化阶段
1》constructor 【主线程结束之后执行,异步执行】
1.通过super将绑定在组件身上的props赋值给this.props
2.定义state
3.普通函数绑定this
2》componentWillMount 【新版本舍弃】
1.组件即将挂载
2.拿到state,没有真实DOM
3》render 【底层 React.createElement】
1.解析this.props / this.state
2.将jsx元素渲染为vdom对象原型,生成虚拟DOM
3.不可以使用setState() 【单线程,解析同时不可以展示】
4》componentDidMount 【】
1.组件挂载结束
2.数据请求,数据修改
3.拿到真实DOM 第三方化组件实例
2.更新阶段 【setState/forceUpdate】
1》componentWillReceiveProps(nextProps) 【只针对props,state没有这个钩子函数】
1.获取最新的属性
2.用于判断组件当前属性是否改变
2》shouldComponentUpdate(nextProps,nextState)
1.组件是否更新
2.写上必须要有返回值,布尔值
3.性能优化
4.props拿到的是不一样的值,state拿到的都是最新的值
3》componentWillUpdate 【新版本舍弃】
1.组件即将更新
4》render
5》componentDidUpdate
1.组件更新结束
2.真实DOM生成,获取数据,更新数据
3.销毁阶段
1》componentWillUnmount
1.清除无用的实例和事件
2.定时器,第三方实例
4.错误捕获阶段
1》componentDidCatch
1.捕获子组件throw出来的错误
13.高阶组件
1.复用组件逻辑,一种设计模式,
2.HOC 【High Order Component】
3.一个封装函数,接受一个组件作为参数
4.返回值是一个类组件
export function HocComp(Comp){
return class _ extends Component{
// 复用逻辑
render(){
return <Comp/>
}
}
}
const withTab = HocComp(Tab)
14.受控组件 / 非受控组件
表单元素的value值受组件的state控制,这个表单元素称为受控组件
handle = e => {
this.setState({
val:e.target.value
})
}
<input value={this.val} onChange={this.handle} />
非受控组件
<input defaultValue={this.val} />
15.craco.config.js配置
1》反向代理
devServer:{
proxy:{
'/api':{
target:'https://m.moayan.com',
changeOrigin:true //使用当前服务器代理目标源
pathRewrite:{
'^/api':'' //后端没有统一词,需要进行路径的重写
}
}
}
}
2》webpack:{
alias:{
'@':path.join(__dirname,'./src')
}
}
16.路由
1.SPA 单页面的切换
2.react-router react-router-dom
1》确定路由模式
HashRouter / BrowserRouter
import {BrowserRouter as Router} from 'react-router-dom'
<Router>
<App/>
</Router>
路由配置数组 component:lazy(()=>import('@/page/home')) //路由懒加载
路由配置文件
<Suspense fallback={<div>加载中...</div>}> //转场组件
<Switch> //只显示一个组件
<Redirect from='/' to='/home' exact /> //重定向组件,exact表示路由路径完全匹配
< routes.map( (item,index) => <Route key={index} path={item.path} component={item.component} /> )>
</Switch>
</Suspense>
2》导航
<NavLink to='/home' activeClassName='active'> 首页 </NavLink> //待带激活
<Link to='/user'> 个人中心 </Link> //只是跳转
编程式导航
history location match
history (push,go,goBack)
location (pathname,search,state)
3》动态路由
<Link
to={{
pathname='/list/1'
search:?a=1&b=2&c=3 //查询参数
state:{
title:'商品1' //路由元信息
}
}}
</Link>
处理查找字符串:qs.parse(search.slice(1))
4》路由拦截 判断有无token,有则显示路由,没有跳转登录页面
6》路由鉴权 获取用户身份,在路由中添加自定义选项,
5》路由监听 componentWillReceiveProps
17. Hooks (函数组件) loadsh
1. useState 【定义state,修改state】
1》复杂数据类型不能直接修改
2. useEffect 【实现类组件的componentDidMount/componentDIdUpdate/componentWillUnmout功能】
1》第一个参数回调函数,
2》第二个参数空数组,执行一次
3》第二个参数有值,表示监听这个值得变化,才会触发回调函数
4》useEffect可以写多个
5》第二个参数可以是多个state
3. useContext 【实现跨组件通信】
4. useRef 【用于绑定元素/组件】
1》元素的获取
const pEle = useRef(null)
function getP (){
console.log(pEle.current)
}
<p ref={pEle} ></p>
2》组件的获取
ref不能绑定函数组件
需要使用React.forWardRef(Hello)
使用useImperativeHandle抓取子组件的方法,第一个参数ref,第二个参数回调函数
useImperativeHandle(ref,()=>({
a:1,
add(){
setCount(preCount=>preCount+1)
}
}))
5. useImperativeHandle 【搭配useRef使用,获取函数组件中定义的方法】
6. useMemo 【函数组件优化】
const memoList = useMemo(()=>renderList(),[list])
7. useCallback 【函数组件优化】
18.自定义Hook
就是一个函数
()可以接受数据
export function useStatus(data){
if(data.a){
//做操作
}
if(data.b){
//做操作
}
}
不可以嵌套Hook