React一些不常用知识
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
错误边界(开发环境下依旧会报错)
- 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
解释一下官方的这个例子
- 给Mouse组件传一个属性render(也可以叫其他名字),属性是一个高级组件
{function(mouse) {return < Cat mouse={mouse} />}
- 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
此文大部分参考 官网文档
(完)
0条看法
最新最后最热
等待你的评论