React概略

react中为何用bind
  1. 因为react事件中this默认是undefined
  2. 最好在 constructor中写 修改方法的this指向 不要在 render中的dom上写 因为bind是返回一个新的函数 如果在dom上写 点击一次执行一次bind返回一次新的函数 而如果在constructor中写的话 只有组件初始化的时候返回一次就行了 例如 render dom 中 onClick = this.clickHandler 在constructor中写 this.clickHandler = this.clickHandler.bind(this)
  3. 也可以使用箭头函数 更好 不用使用bind
react中的event
  1. event是SynthetiEvent,是模拟出来DOM事件所有的能力
  2. event.nativeEvent 是原生事件对象
  3. 所有的事件,都被挂载到document上
  4. 和DOM事件不一样,和 vue事件也不一样
setState
  1. 使用不可变值 就是不能使用state直接改 要使用setState,
  2. !!!!不可变值:在setState里面不能直接使用 push pop splice等 这样违反不可变值,如果用的话 比如数组 先用slice方法创建一个副本 修改这个副本里面的值就行,不会影响原数组,类似深拷贝的功能,对象的话不能直接在setState里面设置对象可以使用Object.assign 或者 …来进行扩展
  3. !!!!异步同步:setState直接使用的话 比如一个点击事件 点击+1 如果setState后立即打印 则是异步的 获取的是上一个属性值,但是如果点击完成之后执行一个定时器 在这个定时器中执行setState 然后立即打印 可以获得当前改变的值,还有就是addeventlistener中绑定一个click事件 然后setstate后立即打印 也是同步获取当前改变的值的
  4. !!!!执行合并:setState如果 count = 0 然后 点击事件中执行三次 setState({count:this.state.count+1}) 打印过后还是1 合并了 ,但是如果setState(()=>{}) 传入一个函数 然后都+1的话 就不会被合并了
组件生命周期
  1. 单个组件生命周期如下图所示:
    React概略_第1张图片
  2. 父子组件的生命周期执行是跟vue中一样的 详细可见vue概略这篇博客
  3. 还有个shouldComponentUpdate进行性能优化的 可根据这个来控制render需不需要更新
函数组件
  1. 它是一个纯函数,输入props,输出JSX
  2. 没有实例,没有生命周期,没有state
  3. 不能扩展其他方法
calss组件就是平时写的组件 这里不再赘述
函数组件
function List(props) {
   const { list } = this.props
   return 
    return
  • xxx
}

React高级特性

非受控组件
  1. 什么时候必须通过操作dom 用setState的时候不行 那么就要使用非受控组件了,如点击按钮的时候获取选择上传文件的name名称,比如某些富文本编辑器
  2. 优先使用受控组件,符合react设计原则
portals(传送门)
  1. 组件默认会按照既定层次嵌套渲染
  2. 如何让组件渲染到父组件以外?使用portals 请看以下示例
  3. 使用场景: 父组件太小且 overflow:hidden,父组件z-index值太小,fixed需要放在body第一层级
render() {
    //正常渲染 此时父组件就是调用此组件父组件
    return 
{this.props.children} //类似vue slot
//使用Portals渲染到body上面此时父组件就是body了应用场景适用于当前组件是fixed定位的 当然也可以渲染到别的组件中 但是组件结构还是一样的 如果想渲染到其他组件上后面的document.body改下 return ReactDOM.createPortal(
{this.props.children}
,document.body ) }
context(上下文)
  1. 公共信息(语言,主题)如何传递给每个组件
  2. 使用pops的话太繁琐,使用redux小题大做
  3. 函数组件和class组件写法不一样
异步组件
  1. import()
  2. React.lazy
  3. React.Suspense
const ContextDemo = React.lazy(()=> import('./ContextDemo'))
render(){
  return 

引入动态组件

Loading...
}>
1. 强制刷新,可看到loading 看不到设置下网速 2. 看network的js加载 会把动态引入的组件重新打个包引入异步加载 }
性能优化
  1. shouldComponentUpdate(简称SCU) 使用方法就是判断前后state值有没有改变 如果有改变就return true 渲染 如果没有改变就return false不渲染
  2. 因为react有个默认机制 父组件更新 子组件也默认更新 所以这时候就要用到SCU了
  3. 如果没有遵循state不可变值(我的理解就是不要在setState的时候使用改变state中原数组的写法 如 push pop等)的写法 SCU不会起作用
pureComponent(纯组件)和memo
  1. pureComponent,SCU中实现了浅比较,因为深度递归比较的话 比较消耗性能 类似vdom的比较 如果深度全面比较的话时间复杂度是O(n^3)vdom是同层次一层一层比较 如果不同直接渲染 这样时间复杂度就优化为O(n)了
  2. memo是函数组件中的pureComponent (函数组件与class组件的区别可看本文章中函数组件那一小结)
immutable.js
  1. 如果彻底拥抱不可变值的话 就引用它
  2. 基于共享数据(不是深拷贝,类似深拷贝),速度好
  3. 有一定的学习和迁移成本,按需使用
高阶组件(关于组件公共逻辑的抽离)
  1. mixin,已被react弃用
  2. 高阶组件HOC
//高阶组件不是一种功能,而是一种模式
const HOCFactory = (Component) => {
  class withMouseComponent extends React.Component{
  constructor(props) {
     super(props)
     this.state = { 
        x:0,
        y:0
      }
   }
   handleMouseMove = (event) =>{
     this.setState({
        x: event.clientX,
        y: event.clientY
      })
   }
   //在此定义多个组件的公共逻辑
	   render(){
	       return  
//返回拼装的结果,这里这个this.props是透传props 是在调用的父组件中传递参数的话 就可以在 WrappedComponent1这些组件中获取props.属性名获取属性值了 vue中通过$props v-bind透传属性 } } } return withMouseComponent //引用的话就是 const EnhancedComponent1 = HOCFactory(WrappedComponent1) //EnhancedComponent1组件中可以通过props.mouse接收公共逻辑传回来的值 const EnhancedComponent2 = HOCFactory(WrappedComponent2) vue如何实现高级组件?
  1. Render Props
Redux
  1. 单向数据流概述 dispatch(action) ->reducer ->newState ->subscribe触发通知
    React概略_第2张图片
    上面的图表示了redux的一个简单的数据流模式 下面的是加了redux中间件的一些处理逻辑 redux的中间件在dispatch里面加上
    React概略_第3张图片
    上图跟图一绿色的是一样的原理 view层触发action然后触发dispatch ->dispach可能有中间件 side 又重新触发了dispatch 然后传给reducer 然后返回一个新的state -> 触发视图更新

React原理

JSX本质是什么
  1. Vue的模版不是html JSX也不是js
  2. 可以通过babel试一试 来编写jsx 看最后会编译成什么
  3. 是通过React.createElement()来实现的 最后返回vnode
事件机制
  1. 所有的事件挂载到document上
  2. event不是原生的,是SyntheticEvent合成事件对象
  3. 和Vue事件不同,和DOM事件也不同
    React概略_第4张图片
  4. react 事件统一绑定到document上面 通过合成事件层派发事件 怎么派发呢 通过target知道是谁触发的 然后就知道触发组件下哪个dom元素绑定了onclick事件
react为什么要合成事件机制?
  1. 更好兼容性与跨平台 比如从pc端到native不用重写事件 只需要改合成事件机制里面的逻辑就行了
  2. 事件统一挂载到document上面,减少内存消耗,避免频繁解绑(例如销毁dom元素的时候不需要解绑事件 !!react事件看似挂载到标签上面的 实际是统一挂载在document上的)
  3. 方便事件的统一管理(如事物机制)
setState和batchUpdate机制

React概略_第5张图片

  1. 如上图所示 setState主流程判断 如果处于batch update 就异步更新 如果不处于 则同步更新 batch update是什么
    React概略_第6张图片
  2. 如上图所示 可以把一个事件开始执行里面看作有个隐藏的属性isBatchingUpdates 这个属性在事件开始时为true 在事件结束时为false react中setState的同步异步就根据它的布尔值进行判断
  3. 由上可得出结论:setState无所谓同步还是异步,就看它是否命中batchUpdate机制,而这个机制的判断条件就是判断isBatchingUpdates,在react中生命周期(和他所调用的函数),事件(和他所调用的函数)这些react能管到的入口就能命中batchUpdate机制,而 setTimeout ,DOM注册事件这种react管不到的入口 就不能命中batchUpdate机制

react性能优化

  1. 减少函数bind this的次数
  2. 合理使用SCU和memo
  3. 合理使用immutable.js
  4. webpack
  5. 图片懒加载之类的 还有SSR
可能会有的性能问题
  1. js是单线程的,且和DOM渲染公用一个线程,当组件足够复杂,组件更新时计算和渲染都压力大,同时再有DOM操作需求的时候(动画,鼠标拖拽等),将卡顿
解决方案 fiber(react内部运行机制)
  1. 将reconciliation(js计算如diff时)阶段进行任务拆分(commit(dom渲染)无法拆分),DOM如果需要渲染时暂停,空闲时回复,通过window.requestIdleCallback这个API来判断是否需要DOM渲染

react和vue

相同点
  1. 都支持组件化
  2. 都是数据驱动视图
  3. 都是用vdom操作DOM
不同点
  1. react使用jsx拥抱js,Vue使用模版拥抱html
  2. react函数式编程,vue是声明式的编程
  3. react比vue学习陡峭

你可能感兴趣的:(react)