读书笔记(十):react

1.JSX
直观上看,JSX是将HTML直接嵌入了JS代码中。它让前端实现真正意义上的组件化,通过函数抽离或IIFE(立即执行函数)可以调试JSX。
JSX会被编译为React.createElement,而React.createElement的底层逻辑是无法运行js的,只能渲染一个结果。因此,JSX中除了js表达式不能直接写js语法。JSX只是函数调用和表达式的语法糖。

2.setState
setState方法并不总是能够立刻更新组件,它可能会延迟更新,这样在通过this.state读取内容时,就有可能获取不到最新的状态值。这样的设计是为了通过延迟更新获得更好的性能。
所谓的延迟更新并不是针对所有情况的,实际上,在React控制之内的事件处理过程中,setState不会同步更新this.state;而对于控制之外的情况,会同步执行。

onClick () {
  this.setState({})
}

componentDidMount () {
  document.querySelectorAll('#btn').addEventListener('click', this.onClick)
}

render() {
  return (
    <>
      <button id="btn">out</button>
      <button onClick={this.onClick}>in</button>
    </>
  )
}

在id为btn的button上绑定的事件,是在componentDIdMount方法中通过添加事件监听完成更新的,这是脱离于react事件之外的事件,因此它是同步的;而button上绑定的事件处理函数对应的setState是异步更新的。

promise化setState解决状态间的回调地狱问题:

const setStatePromise = (me, state) => {
  new Promise(resolve => {
    me.setState(state, () => {
      resolve()
    })
  })
}

3.合成事件
react中事件机制并不是原生的那一套,没有绑定在原生DOM上,大多数事件绑定在document上(除了少数不会冒泡到document的事件,如video等)。触发的事件也是对原生事件的包装,并不是原生event对象。合成事件对象将会被重用,在调用事件回调函数后,合成事件对象上的所有属性都将会被废弃,可以大大节省内存,而不会频繁地创建和销毁事件对象。

这样的事件系统设计,无疑会使性能有所提升,但会引发几个潜在现象:

  • 异步访问事件对象

    function handleClick (e) {
      console.log(e)
      e.persist()
      setTimeout(() => {
        console.log(e)
      }, 0)
    }
    

    当所有事件处理函数被调用之后,其所有属性都会被置空。如果你需要在事件处理函数运行之后获取事件对象的属性,你需要调用 e.persist()持久化合成事件。

  • 阻止原生事件冒泡

    handleClick = e => {
      console.log('click')
      e.nativeEvent.stopImmediatePropagation()
    }
    

    直接使用e.stopPropagation不能阻止原生事件冒泡,因为事件早已经冒泡到了document上,react在事件冒泡到document上时才能够处理事件。可以通过合成事件上的nativeEvent属性访问原生事件,原生事件上的stopImmediatePropagation方法除了能阻止冒泡,还能阻止当前元素剩余的、同类型事件的执行。

react在进行element差异比较时,由于key的存在,可以准确地判断出该节点在新集合中是否存在,极大地提高了效率。但由于DOM节点移动操作开销昂贵,对于简单的node文本更改,不需要进行类似的diff过程,只需要更改dom.textContent即可,这时不加key的性能更高。

4.组件
组件的职责尽可能的保持单一,数据的获取和数据的渲染分开进行,这样在修改对应部分的时候不影响另一部分的使用,必要的时候可以使用高阶组件强制保持单一职责。

组件的封装秉承封装性,使组件的state结构只有自己知道。

5.数据状态管理

  • React的state是在组件内部维护的数据,当某项state需要与其他组件共享时,可以通过props完成通信。从实践上来看,需要相对顶层的组件维护共享的state并提供修改此项state的方法,都要传给子孙组件。
  • 使用Redux,在store中集中管理维护数据。任何需要访问并更新数据的组件都需要接入redux,借助容器组件完成订阅。

根据数据的持久度,不同数据的状态可分为:

  • 快速变更型:某些原子级别的信息,显著特点是变更频率快。比如,文本输入框中的值随着用户输入在短时间内持续发生变化。这类数据显然更适合在React组件内维护。
  • 中等持续型:在页面刷新前保持稳定。比如,异步请求接口通过ajax方式获取的数据,或者用户编辑提交的数据。这类数据较为通用,也许会被不同组件所使用,数据维护在redux store中,通过connect方法和组件进行连接。
  • 长远稳定型:在页面多次刷新或多次访问期间都保持不变的数据。这类数据适合保存在服务器端数据库或浏览器的本地存储。

redux的限制体现在:

  • 开发者要写很多“模式代码”,繁琐且重复。
  • 需要使用objects或arrays描述状态。
  • 需要使用plain objects 及actions来描述变化。
  • 需要纯函数去处理变化。
  • 要将应用中的状态抽象到store。

Mobx通过将对象和数组包装为可观察对象,隐藏了大部分样板代码,比redux更加简洁,也更加魔幻,像是进行了双向绑定。

6.函数式组件
面向生命周期编程以及class声明组件面向对象的行为不符合初衷,因此推出了函数式组件。组件只负责接收数据并渲染,清爽而直接。
react hook使开发者按业务逻辑拆分代码,而不是按生命周期,解决了函数式组件完全无状态的问题。

const Component = React.lazy(() => import())

export const AsyncComponent = props => {
  <React.Suspense fallback={<Loading />}>
  	<Component {...props} />
  </React.Suspense>
}

React.lazy带来了延迟加载的能力,封装动态import组件,import返回一个promise对象。
React.Suspense增加了组件异步(中断)渲染的能力,打破了之前同步渲染整个组件的格局。组件设置了fallback,当发现Component是一个promise类型,且没有被决议时,就启用fallback提供的组件,以便在等待网络返回结果时进行服务器端渲染。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值