<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [http://www.zhufengpeixun.cn/2020/html/62.4.react-optimize.html#t65.%20%E9%95%BF%E5%88%97%E8%A1%A8%E4%BC%98%E5%8C%96](http://www.zhufengpeixun.cn/2020/html/62.4.react-optimize.html#t65.%20%E9%95%BF%E5%88%97%E8%A1%A8%E4%BC%98%E5%8C%96) **** 骨架屏模板 [https://danilowoz.com/create-content-loader/](https://danilowoz.com/create-content-loader/) ## 1\. 使用React.Fragment * 使用`React.Fragment`來避免向 DOM 添加額外的節點 ~~~ import React, { Component } from 'react'; import ReactDOM from 'react-dom'; class Users extends React.Component { render() { return ( <React.Fragment> <div>用戶1</div> <div>用戶2</div> </React.Fragment> ); } } ReactDOM.render(<Users />, document.querySelector('#root')); ~~~ ## 2\. 使用 React.Lazy 延遲加載組件 * `React.Lazy`幫助我們按需加載組件,從而減少我們應用程序的加載時間,因為只加載我們所需的組件。 * `React.lazy`接受一個函數,這個函數內部調用 import() 動態導入。它必須返回一個 Promise,該 Promise 需要 resolve 一個 defalut export 的 React 組件。 * React.Suspense 用于包裝延遲組件以在加載組件時顯示后備內容。 ~~~ import React, { Component,lazy, Suspense } from 'react' import ReactDOM from 'react-dom'; import Loading from './components/Loading'; const AppTitle = lazy(()=>import(/* webpackChunkName: "title" */'./components/Title')) class App extends Component{ state = {visible:false} show = ()=>{ this.setState({visible:true}); } render() { return ( <> {this.state.visible&&( <Suspense fallback={<Loading/>}> <AppTitle/> </Suspense> )} <button onClick={this.show}>加載</button> </> ) } } ReactDOM.render(<App />, document.querySelector('#root')); ~~~ ## 3\. 錯誤邊界(Error Boundaries) * 如果當一個組件異步加載下載js文件時,網絡錯誤,無法下載 js 文件 * Suspense 無法處理這種錯誤情況, 在 react 中有一個 錯誤邊界 (Error Boundaries)的概念,用來解決這種問題,它是利用了 react 生命周期的 componetDidCatch 方法來處理 * 有兩種方式,一種是 生命周期 componentDidCatch 來處理錯誤,還有一種 是 靜態方法 static getDerivedStateFromError 來處理錯誤, * 請使用`static getDerivedStateFromError()`渲染備用 UI ,使用 componentDidCatch() 打印錯誤信息。 ~~~ import React, { Component,lazy, Suspense } from 'react' import ReactDOM from 'react-dom'; import Loading from './components/Loading'; const AppTitle = lazy(()=>import(/* webpackChunkName: "title" */'./components/Title')) class App extends Component{ state = {visible:false,isError: false} show = ()=>{ this.setState({visible:true}); } static getDerivedStateFromError(error) { return { isError: true }; } componentDidCatch (err, info) { console.log(err, info) } render() { if (this.state.isError) { return (<div>error</div>) } return ( <> {this.state.visible&&( <Suspense fallback={<Loading/>}> <AppTitle/> </Suspense> )} <button onClick={this.show}>加載</button> </> ) } } ReactDOM.render(<App />, document.querySelector('#root')); ~~~ ## 4\. PureComponent * 當一個組件的`props`或`state`變更,React 會將最新返回的元素與之前渲染的元素進行對比,以此決定是否有必要更新真實的 DOM,當它們不相同時 React 會更新該 DOM。 * 如果渲染的組件非常多時可以通過覆蓋生命周期方法 shouldComponentUpdate 來進行優化 * shouldComponentUpdate 方法會在重新渲染前被觸發。其默認實現是返回 true,如果組件不需要更新,可以在`shouldComponentUpdate`中返回 false 來跳過整個渲染過程。其包括該組件的 render 調用以及之后的操作 * PureComponent通過prop和state的淺比較來實現`shouldComponentUpdate` ### 3.1 App.js ~~~ import React from 'react'; import {Button,message} from 'antd'; import PureComponent from './PureComponent'; export default class App extends PureComponent{ state = { title:'計數器', number:0 } add = ()=>{ this.setState({number:this.state.number+parseInt(this.amount.value)}); } render(){ console.log('App render'); return ( <div> <Title2 title={this.state.title}/> <Counter number={this.state.number}/> <input ref={inst=>this.amount = inst}/> <button onClick={this.add}>+</button> </div> ) } } class Counter extends PureComponent{ render(){ console.log('Counter render'); return ( <p>{this.props.number}</p> ) } } //類組件可以用繼承 class Title extends PureComponent{ render(){ console.log('Title render'); return ( <p>{this.props.title}</p> ) } } //函數組件可以和memo const Title2 = React.memo(props=>{ console.log('Title2 render'); return <p>{props.title}</p>; }); //memo的實現 function memo(func){ class Proxy extends PureComponent{ render(){ return func(this.props); } } return Proxy; } //memo的另一種實現 接收一個函數組件 function memo2(Func){ class Proxy extends PureComponent{ render(){ return <Func {...this.props}/> } } return Proxy; } ~~~ ### 3.2 PureComponent ~~~ import React from 'react'; function shallowEqual(obj1,obj2){ if(obj1 === obj2){ return true; } if(typeof obj1 != 'object' || obj1 === null ||typeof obj2 != 'object' || obj2 === null ){ return false; } let keys1 = Object.keys(obj1); let keys2 = Object.keys(obj2); if(keys1.length != keys2.length){ return false; } for(let key of keys1){ if(!obj2.hasOwnProperty(key) || obj1[key] !== obj2[key]){ return false; } } return true; } export default class PureComponent extends React.Component{ isPureReactComponent = true shouldComponentUpdate(nextProps,nextState){ return !shallowEqual(this.props,nextProps)||!shallowEqual(this.state,nextState) } } ~~~ ## 5\. 長列表優化 * 用數組保存所有列表元素的位置,只渲染可視區內的列表元素,當可視區滾動時,根據滾動的offset大小以及所有列表元素的位置,計算在可視區應該渲染哪些元素 * [react-window](https://www.npmjs.com/package/react-window) * [fixed-size](https://react-window.now.sh/#/examples/list/fixed-size) * [react-virtualized](https://www.npmjs.com/package/react-virtualized) ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>長列表優化</title> <style> *{ margin: 0; padding: 0; } ul,li{ list-style: none; } </style> </head> <body> <div id="container" style="height:150px;overflow:auto"> <ul id="list"></ul> <div id="content-placeholder"></div> </div> <script> const ITEM_HEIGHT = 30; const ITEM_COUNT = 10; window.onload = function() { const container = document.querySelector("#container"); const containerHeight = container.clientHeight; const list = document.querySelector("#list"); list.style.height = containerHeight+'px'; const visibleCount = Math.ceil(containerHeight / ITEM_HEIGHT); const placeholder = document.querySelector("#content-placeholder"); list.appendChild(renderNodes(0, visibleCount)); placeholder.style.height = (ITEM_COUNT * ITEM_HEIGHT -containerHeight) + "px"; container.addEventListener("scroll", function() { list.style.webkitTransform = `translateY(${container.scrollTop}px)`; list.innerHTML = ""; const firstIndex = Math.floor(container.scrollTop / ITEM_HEIGHT); list.appendChild(renderNodes(firstIndex, firstIndex + visibleCount)); }); }; function renderNodes(from, to) { const fragment = document.createDocumentFragment(); for (let i = from; i < to; i++) { const el = document.createElement("li"); el.style.height='30px'; el.innerHTML = i + 1; fragment.appendChild(el); } return fragment; } </script> </body> </html> ~~~ ~~~ import React, { Component, lazy, Suspense } from "react"; import ReactDOM from "react-dom"; import { FixedSizeList as List } from 'react-window'; const Row = ({ index, style }) => ( <div style={style}>Row {index}</div> ); const Container = () => ( <List height={150} itemCount={1000} itemSize={35} width={300} > {Row} </List> ); ReactDOM.render(<Container/>, document.querySelector("#root")); ~~~ ~~~ import React, { Component, lazy, Suspense } from "react"; import ReactDOM from "react-dom"; //import { FixedSizeList as List } from 'react-window'; class List extends React.Component{ state = {start:1} constructor(){ super(); this.containerRef = React.createRef(); } componentDidMount(){ this.containerRef.current.addEventListener('scroll',()=>{ let scrollTop = this.containerRef.current.scrollTop; let start = Math.floor(scrollTop/this.props.itemSize);//起始的索引 this.setState({start}); }); } render(){ let {width,height,itemCount,itemSize} = this.props; let containerStyle = {height,width,position:'relative',border:'1px solid red',overflow:'auto'}; let itemStyle = {height:itemSize,width:'100%',position:'absolute',left:0,top:0}; let render = this.props.children; let children = []; let size = Math.floor(height/itemSize)+1;//每頁的條數 for(let index=this.state.start;index<=this.state.start+size;index++){ let style = {...itemStyle,top:(index-1)*itemSize}; children.push(render({index,style})); } let topStyle = {width:'100%',height:itemSize*this.start}; return ( <div style={containerStyle} ref={this.containerRef}> <div style={{width:'100%',height:itemSize*itemCount}}> {children} </div> </div> ) } } const Row = ({ index, style }) => ( <div key={index} style={style}>Row{index}</div> ); const Container = () => ( <List height={150} itemCount={100} itemSize={30} width={300} > {Row} </List> ); ReactDOM.render(<Container/>, document.querySelector("#root")); ~~~ ## 6\. react devtool * [react-devtools](https://github.com/facebook/react-devtools) * [profiler](http://react.html.cn/blog/2018/09/10/introducing-the-react-profiler.html) * [react-flame-graph](https://react-flame-graph.now.sh/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看