LazyLoad 组件

先去配置中修改属性:
dynamicImport: true,
该属性主要是配置按需加载的问题
主要用到 react 中的两个东西:

  • lazy 方法
  • Suspense 标签

调用 react 中的 lazy方法,该方法接收一个调用 import 方法的回调函数并且返回一个 Promise 对象
Suspense 标签接收一个 fallback 参数,fallback 是在子组件未解析完前执行的,主要是在里面渲染一些 loading 的效果。
index

  1. import React, { lazy, Suspense } from 'react'
  2. // import Demo from './demo'
  3. const Demo = lazy(() => import('./demo'))
  4. const Index = () => {
  5. return (
  6. <div>
  7. <Suspense fallback={<h1>loading...</h1>}>
  8. <Demo />
  9. </Suspense>
  10. </div>
  11. )
  12. }
  13. export default Index

demo

  1. import React from 'react'
  2. function Demo() {
  3. return <div>demo</div>
  4. }
  5. export default Demo

当然现在的网络环境,直接显示效果是没有这么明显的。想要看到明显loading的效果:

  • 直接在控制台中设置网络为节流模式

懒加载的主要目的是优化前端性能,减少请求或延迟请求数,常用有这么几种方法:

  1. 使用setTimeoutsetInterval纯粹的延迟加载
  2. 条件加载,符合某些条件或者触发了某些事件再开始异步加载
  3. 可视区加载,即利用监控导航条来加载可以看到的区域

这里是第一种

  1. import React, { lazy, Suspense, useState, useEffect } from 'react'
  2. const LazyLoad = props => {
  3. const _renderLazy = () => {
  4. let Lazy
  5. const { component, delay, ...restProps } = props
  6. if (!component || component.constructor.name !== 'Promise') {
  7. Lazy = import('./error')
  8. }
  9. Lazy = lazy(() => {
  10. return new Promise((resolve, reject) => {
  11. setTimeout(() => {
  12. resolve(component)
  13. })
  14. }, delay || 300)
  15. })
  16. return <Lazy {...restProps} />
  17. }
  18. return (
  19. <div>
  20. <Suspense fallback={<h5>loading...</h5>}>
  21. {_renderLazy()}
  22. </Suspense>
  23. </div>
  24. )
  25. }
  26. export default LazyLoad

ErrorBoundary 组件

对组件进行错误处理
在实际项目当中会遇到因为某些错误导致页面直接报错、白屏的问题,这会带来很不好的开发体验或是差劲的用户体验。
针对错误处理,react 提供了两个构造函数
官网中文文档|错误边界

  • getDerivedStateFromError 他只能检测父组件中子组件发生的错误,而不能检测自身发生的错误。
  • componentDidCatch ```jsx import React, { Component } from ‘react’

export default class ErrorBoundary extends Component { constructor(props) { super(props) this.state = { flag: false, } }

static getDerivedStateFromError(error) { console.log(‘eee’, error) return { flag: true, } }

/* error: 抛出的错误

  • info: 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息 在这其中做日志相关的操作,因为其返回的信息会相对来说比较全面一点 */ componentDidCatch(error, info) {} render() { return (
    {this.state.flag ? (
    1. <h1>发生了未料到的错误,请稍微再刷新试试</h1>
    ) : (
    1. this.props.children
    )}
    ) } }
  1. 当这个组件并不是处理错误信息的万能方法,当遇到类似点击事件引发的错误时以及一些异步函数内部导致的错误时,就无法进行检测。
  2. <a name="TCYLH"></a>
  3. ### Modal 组件
  4. 基于 `[createPotal](https://zh-hans.reactjs.org/docs/react-dom.html#createportal)` 这个api
  5. > 创建 portal。[Portal](https://zh-hans.reactjs.org/docs/portals.html) 将提供一种将子节点渲染到 DOM 节点中的方式,该节点存在于 DOM 组件的层次结构之外。
  6. 可以借此用来处理自定义弹窗、输入框以及对话框等场景。<br />**CreateProtal**
  7. ```jsx
  8. import React, { useEffect } from 'react'
  9. import ReactDOM from 'react-dom'
  10. const CreatePortal = props => {
  11. const { children } = props
  12. const body = document.querySelector('body')
  13. const el = document.createElement('div')
  14. useEffect(() => {
  15. el.setAttribute('id', 'portal-root')
  16. body.appendChild(el)
  17. return () => {
  18. body.removeChild(el)
  19. }
  20. }, [body, el])
  21. return ReactDOM.createPortal(children, el)
  22. }
  23. export default CreatePortal

Modal

  1. import React from 'react'
  2. import CreateProtal from '../CreatePortal'
  3. import { Icon } from 'antd-mobile'
  4. const Styles = {
  5. modal: {
  6. position: 'relative',
  7. top: '0',
  8. left: '0',
  9. zIndex: '999',
  10. },
  11. body: {
  12. backgroundColor: '#fff',
  13. position: 'fixed',
  14. height: '100%',
  15. width: '100%',
  16. top: '0',
  17. left: '0',
  18. display: 'flex',
  19. alignItems: 'center',
  20. justifyContent: 'center',
  21. },
  22. close: {
  23. position: 'fixed',
  24. top: '10px',
  25. right: '10px',
  26. },
  27. }
  28. const Modal = props => {
  29. const { children, show } = props
  30. const handleClose = () => {
  31. const { onClose } = props
  32. onClose && onClose()
  33. }
  34. return (
  35. <>
  36. {show ? (
  37. <CreateProtal style={Styles.modal}>
  38. <div style={Styles.body}>
  39. {children}
  40. <Icon
  41. type="cross"
  42. size="lg"
  43. style={Styles.close}
  44. onClick={handleClose}
  45. />
  46. </div>
  47. </CreateProtal>
  48. ) : null}
  49. </>
  50. )
  51. }
  52. export default Modal

测试

  1. import React, { useState } from 'react'
  2. // import CreateProtal from '@/components/CreatePortal'
  3. import Modal from '../../../components/Modal'
  4. import { Button } from 'antd-mobile'
  5. const Index = () => {
  6. const [show, setShow] = useState(false)
  7. const handleClick = () => {
  8. setShow(true)
  9. }
  10. const handleClose = () => {
  11. setShow(false)
  12. }
  13. return (
  14. <div>
  15. <Button type="primary" onClick={handleClick}>
  16. modal
  17. </Button>
  18. <Modal show={show} onClose={handleClose}>
  19. modal
  20. </Modal>
  21. </div>
  22. )
  23. }
  24. export default Index

效果:
GIF.gif