React一些不常用知识

Snipaste_20200519_011057.jpg

react使用lazy()和Suspense实现根据路由进行代码分割

作用:可以加快首页加载时间

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom'; import React, { Suspense, lazy } from 'react'; const Home = lazy(() => import('./home')); const Bar = lazy(() => import('./bar')); const App = () => ( <Router> <Suspense fallback={<div>loading</div>}> <div> <ul> <li><Link to="/">Home></Link></li> <li><Link to="/bar">Bar></Link></li> </ul> </div> <Switch> <Route exact path="/" component={Home} /> <Route path="/bar" component={Bar} /> </Switch> </Suspense> </Router> ) export default App;
          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
import React, { Component } from 'react'; class Home extends Component { render() { return ( <div> Home </div> ); } } export default Home;
          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
import React, { Component } from 'react'; class Bar extends Component { render() { return ( <div> bar </div> ); } } export default Bar
20181205103320491.gif

参考博客

错误边界(开发环境下依旧会报错)

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { error: null, errorInfo: null }; } componentDidCatch(error, errorInfo) { // Catch errors in any components below and re-render with error message this.setState({ error: error, errorInfo: errorInfo }) // You can also log error messages to an error reporting service here } render() { if (this.state.errorInfo) { // Error path return ( <div> <h2>出错了</h2> <details> {this.state.error && this.state.error.toString()} <br /> {this.state.errorInfo.componentStack} </details> </div> ); } // Normally, just render children return this.props.children; } } class BuggyCounter extends React.Component { constructor(props) { super(props); this.state = { counter: 0 }; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(({ counter }) => ({ counter: counter + 1 })); } render() { if (this.state.counter === 5) { // Simulate a JS error throw new Error('I crashed!'); } return <h1>{this.state.counter}</h1>; } } function App() { return ( <div> <p> <b> 错误边界示例 <br /><br /> 单击数字以增加计数器。 <br /> 当计数器达到5时,程序会自动抛出。这将模拟组件中的JavaScript错误。 </b> </p> <hr /> <ErrorBoundary> <p>这两个计数器位于同一个错误边界内。如果一个崩溃,错误边界将同时替换它们。</p> <BuggyCounter /> <BuggyCounter /> </ErrorBoundary> <hr /> <p>这两个计数器都在各自的错误边界内。因此,如果一个崩溃,另一个不会受到影响。</p> <ErrorBoundary><BuggyCounter /></ErrorBoundary> <ErrorBoundary><BuggyCounter /></ErrorBoundary> </div> ); } export default App;

Fragments

相当于Vue的 template 可以无需添加多余的

Portals

Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。 下面是典型应用对话框

App.css

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
#modal-root { position: relative; z-index: 999; } .app { height: 10em; width: 10em; background: lightblue; overflow: hidden; } .modal { background-color: rgba(0,0,0,0.5); position: fixed; height: 100%; width: 100%; top: 0; left: 0; display: flex; align-items: center; justify-content: center; }
          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
import React from 'react'; import ReactDOM from 'react-dom'; import "./App.css" // These two containers are siblings in the DOM const modalRoot = document.getElementById('modal-root'); // Let's create a Modal component that is an abstraction around // the portal API. class Modal extends React.Component { constructor(props) { super(props); // Create a div that we'll render the modal into. Because each // Modal component has its own element, we can render multiple // modal components into the modal container. this.el = document.createElement('div'); } componentDidMount() { // Append the element into the DOM on mount. We'll render // into the modal container element (see the HTML tab). modalRoot.appendChild(this.el); } componentWillUnmount() { // Remove the element from the DOM when we unmount modalRoot.removeChild(this.el); } render() { // Use a portal to render the children into the element return ReactDOM.createPortal( // Any valid React child: JSX, strings, arrays, etc. this.props.children, // A DOM element this.el, ); } } // The Modal component is a normal React component, so we can // render it wherever we like without needing to know that it's // implemented with portals. class App extends React.Component { constructor(props) { super(props); this.state = {showModal: false}; this.handleShow = this.handleShow.bind(this); this.handleHide = this.handleHide.bind(this); } handleShow() { this.setState({showModal: true}); } handleHide() { this.setState({showModal: false}); } render() { // Show a Modal on click. // (In a real app, don't forget to use ARIA attributes // for accessibility!) const modal = this.state.showModal ? ( <Modal> <div className="modal"> <div> With a portal, we can render content into a different part of the DOM, as if it were any other React child. </div> This is being rendered inside the #modal-container div. <button onClick={this.handleHide}>Hide modal</button> </div> </Modal> ) : null; return ( <div className="app"> This div has overflow: hidden. <button onClick={this.handleShow}>Show modal</button> {modal} </div> ); } } export default App

Render Props

这是官方给的一个例子,让一张图片跟随鼠标

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
import img1 from "./cat.jpg" class Cat extends React.Component { render() { const mouse = this.props.mouse; return ( <img src={img1} style={{ position: 'absolute', left: mouse.x, top: mouse.y }} alt=""/> ); } } class Mouse extends React.Component { constructor(props) { super(props); this.handleMouseMove = this.handleMouseMove.bind(this); this.state = { x: 0, y: 0 }; } handleMouseMove(event) { this.setState({ x: event.clientX, y: event.clientY }); } render() { return ( <div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}> {/* Instead of providing a static representation of what <Mouse> renders, use the `render` prop to dynamically determine what to render. */} {this.props.render(this.state)} </div> ); } } class MouseTracker extends React.Component { render() { return ( <div> <h1>移动鼠标!</h1> <Mouse render={mouse => ( <Cat mouse={mouse} /> )}/> </div> ); } } export default MouseTracker

解释一下官方的这个例子

  1. 给Mouse组件传一个属性render(也可以叫其他名字),属性是一个高级组件{function(mouse) {return < Cat mouse={mouse} />}
  2. Mouse用这个函数{this.props.render(this.state)}渲染出这个高阶组件

forceUpdate()

可以用this.forceUpdate()强制渲染 调用 forceUpdate() 将致使组件调用 render() 方法,此操作会跳过该组件的 shouldComponentUpdate()。但其子组件会触发正常的生命周期方法,包括 shouldComponentUpdate() 方法。如果标记发生变化,React 仍将只更新 DOM。

defaultProps

defaultProps 可以为 Class 组件添加默认 props。这一般用于 props 未赋值,但又不能为 null 的情况

React.PureComponent

React.PureComponent 中的 shouldComponentUpdate() 仅作对象的浅层比较。如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果

此外,React.PureComponent 中的 shouldComponentUpdate() 将跳过所有子组件树的 prop 更新。因此,请确保所有子组件也都是“纯”的组件。

下面是一段代码,父组件的渲染并不会影响到子组件

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
class Parent extends React.Component { constructor(props) { console.log("constructor") super(props) this.state = { count: 0 } } add = () => { this.setState((state) => { return { count: state.count + 1 }; }) } render() { console.log('父组件渲染') return ( <div > <div > count:{this.state.count} <button onClick={this.add}>子组件count+1</button> </div> <Son> </Son> </div> ); } } class Son extends React.PureComponent { constructor(props) { console.log("constructor") super(props) this.state = { count: 0 } } render() { console.log('子组件渲染') return ( <div > <div > 子组件 </div> </div> ); } } export default Parent

此文大部分参考 官网文档

———end———
(完)
闭包
Js神兽闭包
韭菜成长记
优秀的交易者,通常都不合群一天不独处,我就会变得虚弱,我不以孤独为荣,但是我却以此为生。
Python 获取IP地址并通过IP查询归属地
获取ip,通过ip-api接口查询归属地,代理改变自己的归属地
谈谈债券,可转债,国债
债券到底是什么?可转债和债券的关系?可转债啥时卖?国债利率上升对股市,经济产生的影响?
Python通过第三方平台转发邮件
完善你的博客评论系统
北高峰爬山
天下第一财神庙,抽了个签
等待你的评论