文章目录
必备-18.react
-
react:渐进式框架(react用的mvc设计模式,vue用的mvvm设计模式)
-
官方网址:https://react.docschina.org/tutorial/tutorial.html
-
npm没有一个很好的移动端框架
-
react的组件库:antdUI组件库、antd-pro
-
redux的发展史:react-redux->dva(集成了redux-saga)->umi[阿里研发的,针对于ract的集成封装框架]
命令
- 创建项目:
npm install -g create-react-app
:下载react脚手架create-react-app my-app
:创建一个react项目yarn: npm i yarn -g
:用yarn代替npm操作
- 启动项目:
npm start/yarn start
:启动当前项目,启动成功会自动跳转到网页
React中JSX渲染的过程?
- 1、基于
babel-preset-react-app
,将jsx渲染为虚拟DOM对象"jsx元素对象"- 一:把jsx语法变为
React.createElement(标签名/组件名,props/null,子节点内容...)
- 所有元素节点都会基于
createElement
处理
- 所有元素节点都会基于
- 二:把
createElement
方法执行,会返回一个对象,我们这个对象称为:jsx对象、虚拟DOM对象[由框架本身自定义,基于对象中的键值对来描述某个DOM节点信息的对象] - 扩展:Vue是基于
vue-template-compiler
把template
语法编译成vnode
- 一:把jsx语法变为
- 2、DOM-DIFF
- 第一次渲染不需要DOM-DIFF
- 视图重新渲染:首先根据最新数据,重新生成一套虚拟DOM对象,然后和上一次虚拟DOM做对比(dom-diff),找到差异化,最后把差异化的部分再去渲染上去!
- 3、基于
ReactDOM.render
把jsx元素对象(虚拟DOM对象),变为真实对象,并插入到#root的容器中- 如果type是标签名,则基于
document.createElement
创建对应的DOM元素对象(真实DOM对象),再把属性以及子节点处理,最后把创建的DOM对象,插入到#root容器中
- 如果type是标签名,则基于
- JSX具有很强的编程性,而template的编程性很弱
React中的组件化
- React中创建组件的方案:函数式组件和类组件
- 函数式组件:每次调用组件,就是把函数执行(且传递props),把返回的jsx进行渲染
- 类组件:每一次调用组件,就是创建类的实例(也会传递props),把render钩子函数中返回的JSX进行渲染
function[静态组件]
- 传递的属性是被冻结的,不能直接修改;想要修改,需要把属性值赋值给其他的变量或状态
- 基于
props.children
实现类似于vue中slot插槽的效果- React.Children.map/toArray
- 类似于具名插槽的修改
- 函数式组件是静态组件,第一次渲染完成后,除非父组件重新调用,否则不会再进行更新
class[动态组件]
- class类组件中的this就是当前组件的实例,其内部会绑定几个属性:
this.props
:父组件传过来的属性this.state
:状态值,自己设定的,相当于vue中的datathis.context
:上下文信息this.refs
:操作DOM
生命周期函数:
- [第一次渲染逻辑]
constructor
(含:初始化属性和状态,以及挂载到实例上的相关操作)componentWillMount
[不安全的]render
componentDidMount
(PS:获取DOM、设置定时器、发送数据请求…)
- [组件更新(重新渲染)逻辑]
- CASE1:基于
this.setState(partialState,nextTickCallback)
修改状态shouldComponentUpdate(nextProps,nextState)
[返回true继续,返回false则停止](可以做更新优化)componentWillUpdate
:[不安全的]render
componentDidUpdate
:nextTickCallback
:(PS一般修改某个状态或者更新后想做啥,都写在这里)
- CASE2:基于
this.forceUpdate(nextTickCallback)
强制更新componentWillUpdate
:跳过了shouldComponentUpdate
render
componentDidUpdate
nextTickCallback
- CASE3:父组件更新也会触发子组件的更新
componentWillReceiveProps
[不安全的]shouldComponentUpdate
- …
- CASE1:基于
- [组件销毁逻辑]
componentWillUnmount
(PS:取消定时器、手动移除自己给DOM元素绑定的事件、编写信息的草稿箱…)
- 要学会constructor中的super、如何设置状态初始值、了解挂载到实例上的内容:
props/state/context/refs
等 - 事件绑定的方法都写为箭头函数[保证函数中的THIS是实例]
- 掌握Vue和React框架的响应式原理
设置属性
在class组件中设置属性的规则:
- 只有在类组件中,我们才能基于官方提供的第三方插件:prop-types设置属性的规则:默认值和类型限定
设置默认值:通过static defaultProps:{}
设置
设置规则校验:
-
第一步:导入
PropTypes
-
第二步:
-
static propTypes={ title:PropTypes.string.isRequired, 。。。 }
-
基于ref获取DOM对象
//给标签起一个ref
<p ref="AA"></p>
//获取
componentDidUpdate(){
this.refs;//[AA]
}
-
项目中:
-
<div ref={x=>this.$AA=x}></div>
-
hooks[钩]组件
-
Hooks组件:在函数(静态)组件的基础上,React新增了一些hooks函数,基于这些函数,也可以让函数组件拥有,状态、生命周期等
-
真实项目中用的最多的就是hooks组件,(只需要渲染一次即可,则用函数组件,不需要使用hooks函数:如果需要状态和周期函数,则使用hooks函数即可):只有非常复杂的组件才是用类组件!
-
React类上提供了很多usexxx开头的Hook函数
-
创建一个状态值:
let [xxx,setXxx]=useState(initial)
:在函数组件中使用状态-
initial
: -
返回值是一个数组:[当前状态的值,修改状态的方法()]
-
执行第二个方法,传递值是多少,就是把状态值改为多少,重点是通知组件重新渲染
-
//创建一个oppNum状态值,并赋值为10 let [oppNum,setoppNum]=useState(10) //修改oppNum setoppNum(20)//将oppNum状态值改为20
-
-
创建一个对象,存多个状态值:
-
//创建两个状态值 let [state,setState]=useState({ supNum:10, oppNum:5 }) //不支持部分状态更改,传递的值是啥,相当于把整个State都改成啥 setState({ supNum:state.supNum+1, oppNum:state.oppNum+1 })
-
-
函数组件与类组件的区别
- 函数组件:
- 优势:快,轻量
- 弊端:静态组件,不能实现基于修改状态,让组件重新渲染的需求
- 没有周期函数、没有状态、也没有对属性进行校验以及操作DOM等机制.
- 类组件:
- 优势:功能全,啥都有
- 弊端:臃肿/庞大、导致相对较慢
- hooks组件:在函数(静态)组件的基础上,React新增了一些hooks函数,基于这些函数,也可以让函数组件拥有,状态、生命周期等
vue与react的响应式原理
-
vue的响应式:用(defineoperty/Proxy),当我们修改状态的时候,内部劫持到,修改数据的同时,也会让视图重新渲染!!->我们只需要直接修改数据即可this.xxx=xxx
-
react的响应式:react对state状态没有做任何的劫持,我们基于
this.state.xxx=xxx
不会触发视图渲染- react可以通过**setState(‘partifyState’,callback)**设置某个状态值,并且通知视图重新渲染
- callback与vue中的
this.$nextTick()
相似,它在componentDidUpdate
事件之后执行
- callback与vue中的
- 也可以用
this.forceUpdate()
强制刷新视图
- react可以通过**setState(‘partifyState’,callback)**设置某个状态值,并且通知视图重新渲染