React知識點總結

2021-01-19 字節愛好者

下面總結一下知識點,便於查看:

1.事件

2.表單

3.setState

4.生命周期

5.函數組件

6.非受控組件

7.Portals

8.context

9.異步組件

10.性能優化

11.高階組件HOC

12.Render Props




事件

1.使用bind

import React from 'react'
class EventDemo extends React.Component { constructor(props) { super(props) this.state = { name: 'zhangsan', }
// 修改方法的 this 指向 this.clickHandler1 = this.clickHandler1.bind(this) } render() { // // this - 使用 bind return <p onClick={this.clickHandler1}> {this.state.name} </p> } clickHandler1() { console.log('this....', this) // this 默認是 undefined this.setState({ name: 'lisi' }) }}
export default EventDemo


2.使用靜態方法

// this - 使用靜態方法return <p onClick={this.clickHandler2}>clickHandler2 {this.state.name}</p>
// 靜態方法,this 指向當前實例clickHandler2 = () => { this.setState({ name: 'lisi' })}

3.event

<a href="https://baidu.com/" onClick={this.clickHandler3}>click me</a>
// 獲取 eventclickHandler3 = (event) => { event.preventDefault() // 阻止默認行為 event.stopPropagation() // 阻止冒泡 console.log('target', event.target) // 指向當前元素,即當前元素觸發 console.log('current target', event.currentTarget) // 指向當前元素,假象!!!
// 注意,event 其實是 React 封裝的。可以看 __proto__.constructor 是 SyntheticEvent 組合事件 console.log('event', event) // 不是原生的 Event ,原生的是 MouseEvent console.log('event.__proto__.constructor', event.__proto__.constructor)
// 原生 event 如下。其 __proto__.constructor 是 MouseEvent console.log('nativeEvent', event.nativeEvent) console.log('nativeEvent target', event.nativeEvent.target) // 指向當前元素,即當前元素觸發 console.log('nativeEvent current target', event.nativeEvent.currentTarget) // 指向 document !!!
// 1. event 是 SyntheticEvent ,模擬出來 DOM 事件所有能力 // 2. event.nativeEvent 是原生事件對象 // 3. 所有的事件,都被掛載到 document 上 // 4. 和 DOM 事件不一樣,和 Vue 事件也不一樣}

結果如下:


表單

受控組件:通過change事件來改變state

import React from 'react'
class FormDemo extends React.Component { constructor(props) { super(props) this.state = {            name: 'curry', info: '個人信息', city: 'beijing', flag: true, gender: 'male' } } render() {
// // 受控組件 // return <div> // <p>{this.state.name}</p> // <label htmlFor="inputName">姓名:</label> {/* 用 htmlFor 代替 for */} // <input id="inputName" value={this.state.name} onChange={this.onInputChange}/> // </div>
// textarea - 使用 value return <div> <textarea value={this.state.info} onChange={this.onTextareaChange}/> <p>{this.state.info}</p> </div>
// // select - 使用 value return <div> <select value={this.state.city} onChange={this.onSelectChange}> <option value="beijing">北京</option> <option value="shanghai">上海</option> <option value="shenzhen">深圳</option> </select> <p>{this.state.city}</p> </div>
// // checkbox return <div> <input type="checkbox" checked={this.state.flag} onChange={this.onCheckboxChange}/> <p>{this.state.flag.toString()}</p> </div>
// // radio return <div> male <input type="radio" name="gender" value="male" checked={this.state.gender === 'male'} onChange={this.onRadioChange}/> female <input type="radio" name="gender" value="female" checked={this.state.gender === 'female'} onChange={this.onRadioChange}/> <p>{this.state.gender}</p> </div> } onInputChange = (e) => { this.setState({ name: e.target.value }) } onTextareaChange = (e) => { this.setState({ info: e.target.value }) } onSelectChange = (e) => { this.setState({ city: e.target.value }) } onCheckboxChange = () => { this.setState({ flag: !this.state.flag }) } onRadioChange = (e) => { this.setState({ gender: e.target.value }) }}
export default FormDemo

setState

1.不可變值

2.可能是異步更新

3.可能會被合併


不可變值:

import React from 'react'
class StateDemo extends React.Component { constructor(props) { super(props)
// 第一,state 要在構造函數中定義 this.state = { count: 0 } } render() { return <div> <p>{this.state.count}</p> <button onClick={this.increase}>累加</button> </div> } increase = () => { // 第二,不要直接修改 state ,使用不可變值 --- // this.state.count++ // 錯誤 this.setState({ count: this.state.count + 1 // SCU }) // 操作數組、對象的的常用形式 // 不可變值(函數式編程,純函數) - 數組 const list5Copy = this.state.list5.slice() list5Copy.splice(2, 0, 'a') // 中間插入/刪除 this.setState({ list1: this.state.list1.concat(100), // 追加 list2: [...this.state.list2, 100], // 追加 list3: this.state.list3.slice(0, 3), // 截取 list4: this.state.list4.filter(item => item > 100), // 篩選 list5: list5Copy // 其他操作 }) // 注意,不能直接對 this.state.list 進行 push pop splice 等,這樣違反不可變值
// 不可變值 - 對象 this.setState({ obj1: Object.assign({}, this.state.obj1, {a: 100}), obj2: {...this.state.obj2, a: 100} }) // 注意,不能直接對 this.state.obj 進行屬性設置,這樣違反不可變值 }}
export default StateDemo


可能是異步更新:

this.setState({    count: this.state.count + 1}, () => {    console.log('count by callback', this.state.count) // 回調函數中可以拿到最新的 state})console.log('count', this.state.count) // 異步的,拿不到最新值

列印如下:



setTimeout 中 setState 是同步的:

// setTimeout 中 setState 是同步的setTimeout(() => {    this.setState({        count: this.state.count + 1    })    console.log('count in setTimeout', this.state.count)}, 0)

列印如下:



自己定義的 DOM 事件,setState 是同步的

 bodyClickHandler = () => {    this.setState({        count: this.state.count + 1    })    console.log('count in body event', this.state.count)}componentDidMount() {    // 自己定義的 DOM 事件,setState 是同步的    document.body.addEventListener('click', this.bodyClickHandler)}


列印如下:


可能會被合併:

傳入對象,會被合併(類似 Object.assign )

 // 傳入對象,會被合併(類似 Object.assign )。執行結果只一次 +1this.setState({    count: this.state.count + 1})this.setState({    count: this.state.count + 1})this.setState({    count: this.state.count + 1})


傳入函數,不會被合併。

  // 傳入函數,不會被合併。執行結果是 +3  this.setState((prevState, props) => {      return {          count: prevState.count + 1      }  })  this.setState((prevState, props) => {      return {          count: prevState.count + 1      }  })  this.setState((prevState, props) => {      return {          count: prevState.count + 1      }  })

生命周期:

http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/



React高級特性:
1.函數組件

2.非受控組件

3.Portals

4.context

5.異步組件

6.性能優化

7.高階組件HOC

8.Render Props



函數組件:

1.純函數,輸入props,輸出jsx

2.沒有實例,沒有生命周期,沒有state


非受控組件:

1.ref

2.defaultValue defaultChexked

3.手動操作dom元素


ref:

第一步:創建ref

第二步:綁定到dom元素

第三步:通過this.nameInputRef.current 獲取dom

第四步:操作dom

使用場景:必須手動操作dom,不能使用state。如上傳文件。

import React from 'react'
class App extends React.Component { constructor(props) { super(props) this.state = { name: 'curry', flag: true, } // 第一步:創建ref this.nameInputRef = React.createRef() // 創建 ref } render() { return <div> {/* 使用 defaultValue 而不是 value ,使用 ref */} // 第二步:綁定到dom元素 <input defaultValue={this.state.name} ref={this.nameInputRef}/> {/* state 並不會隨著改變 */} <span>state.name: {this.state.name}</span> <br/> <button onClick={this.alertName}>alert name</button> </div> } alertName = () => { // 第三步:通過this.nameInputRef.current 獲取dom const elem = this.nameInputRef.current // 通過 ref 獲取 DOM 節點 // 第四步:操作dom alert(elem.value) // 不是 this.state.name }}
export default App

受控組件 vs 非受控組件:

1.優先使用受控組件,符合react設計原則

2.必須操作dom,再使用非受控組件



Portals

作用:讓組件渲染到父組件外


先看下組件正常渲染

import React from 'react'import ReactDOM from 'react-dom'import './style.css'
class App extends React.Component { constructor(props) { super(props) this.state = { } } render() { // // 正常渲染 return <div className="modal"> {this.props.children} {/* vue slot */} </div> }}
export default App

.modal {    position: fixed;    width: 300px;    height: 100px;    top: 100px;    left: 50%;    margin-left: -150px;    background-color: #000;    /* opacity: .2; */    color: #fff;    text-align: center;}

如下:modal渲染到了body裡面。



使用Portals將modal渲染到body第一層。

import React from 'react'import ReactDOM from 'react-dom'import './style.css'
class App extends React.Component { constructor(props) { super(props) this.state = { } } render() { // 使用 Portals 渲染到 body 上。 // fixed 元素要放在 body 上,有更好的瀏覽器兼容性。 return ReactDOM.createPortal( <div className="modal">{this.props.children}</div>, document.body // DOM 節點 ) }}
export default App


如下:modal就在body第一層了。



Portals使用場景:

1.overflow:hidden

2.z-index值太小

3.fixed需要放在body第一層


context:

適用公共信息傳遞給每個組件


第一步:創建 Context 填入默認值(任何一個 js 變量)

const ThemeContext = React.createContext('light')

第二步:將需要共享的數據放到ThemeContext.Provider裡面的value屬性,同時將需要消費共享數據的組件放到ThemeContext.Provider裡面。

直接看下代碼:

<ThemeContext.Provider value={this.state.theme}>    <Toolbar />    <hr/>    <button onClick={this.changeTheme}>change theme</button></ThemeContext.Provider>

第三步:在消費的組件中獲取並使用

ThemedButton.contextType = ThemeContext // 指定 contextType 讀取當前的 theme context。// 底層組件 - class 組件class ThemedButton extends React.Component {    // 指定 contextType 讀取當前的 theme context。    // static contextType = ThemeContext // 也可以用 ThemedButton.contextType = ThemeContext    render() {        const theme = this.context // React 會往上找到最近的 theme Provider,然後使用它的值。        return <div>            <p>button's theme is {theme}</p>        </div>    }}

還可以使用ThemeContext.Consumer來消費共享數據

// 底層組件 - 函數是組件function ThemeLink (props) {    // const theme = this.context // 會報錯。函數式組件沒有實例,即沒有 this
// 函數式組件可以使用 Consumer return <ThemeContext.Consumer> { value => <p>link's theme is {value}</p> } </ThemeContext.Consumer>}

全部代碼如下:

import React from 'react'
// 創建 Context 填入默認值(任何一個 js 變量)const ThemeContext = React.createContext('light')
// 底層組件 - 函數是組件function ThemeLink (props) { // const theme = this.context // 會報錯。函數式組件沒有實例,即沒有 this
// 函數式組件可以使用 Consumer return <ThemeContext.Consumer> { value => <p>link's theme is {value}</p> } </ThemeContext.Consumer>}
// 底層組件 - class 組件class ThemedButton extends React.Component { // 指定 contextType 讀取當前的 theme context。 // static contextType = ThemeContext // 也可以用 ThemedButton.contextType = ThemeContext render() { const theme = this.context // React 會往上找到最近的 theme Provider,然後使用它的值。 return <div> <p>button's theme is {theme}</p> </div> }}ThemedButton.contextType = ThemeContext // 指定 contextType 讀取當前的 theme context。
// 中間的組件再也不必指明往下傳遞 theme 了。function Toolbar(props) { return ( <div> <ThemedButton /> <ThemeLink /> </div> )}
class App extends React.Component { constructor(props) { super(props) this.state = { theme: 'light' } } render() { return <ThemeContext.Provider value={this.state.theme}> <Toolbar /> <hr/> <button onClick={this.changeTheme}>change theme</button> </ThemeContext.Provider> } changeTheme = () => { this.setState({ theme: this.state.theme === 'light' ? 'dark' : 'light' }) }}
export default App

異步組件:
1.import()

2.React.lazy

3.React.Suspense

import React from 'react'
const ContextDemo = React.lazy(() => import('./ContextDemo'))
class App extends React.Component { constructor(props) { super(props) } render() { return <div> <p>引入一個動態組件</p> <hr /> <React.Suspense fallback={<div>Loading...</div>}> <ContextDemo/> </React.Suspense> </div> }}
export default App

性能優化:

1.scu:shouldComponentUpdate

2.PureComponent和React.memo

3.不可變值immutable.js


scu:

默認返回true

shouldComponentUpdate(nextProps, nextState) {    if (nextState.count !== this.state.count) {        return true // 可以渲染    }    return false // 不重複渲染}

父組件更新,子組件也會更新。這時需要scu。


PureComponent:SCU中實現了淺比較, Class組件

React.memo:函數組件



高階組件

接收一個組件,返回一個新組件

import React from 'react'
// 高階組件const withMouse = (Component) => { class withMouseComponent extends React.Component { constructor(props) { super(props) this.state = { x: 0, y: 0 } }
handleMouseMove = (event) => { this.setState({ x: event.clientX, y: event.clientY }) }
render() { return ( <div style={{ height: '500px' }} onMouseMove={this.handleMouseMove}> {/* 1. 透傳所有 props 2. 增加 mouse 屬性 */} <Component {...this.props} mouse={this.state}/> </div> ) } } return withMouseComponent}
const App = (props) => { const a = props.a const { x, y } = props.mouse // 接收 mouse 屬性 return ( <div style={{ height: '500px' }}> <h1>The mouse position is ({x}, {y})</h1> <p>{a}</p> </div> )}
export default withMouse(App) // 返回高階函數


Render props

import React from 'react'import PropTypes from 'prop-types'
class Mouse extends React.Component { constructor(props) { super(props) this.state = { x: 0, y: 0 } }
handleMouseMove = (event) => { this.setState({ x: event.clientX, y: event.clientY }) }
render() { return ( <div style={{ height: '500px' }} onMouseMove={this.handleMouseMove}> {/* 將當前 state 作為 props ,傳遞給 render (render 是一個函數組件) */} {this.props.render(this.state)} </div> ) }}Mouse.propTypes = { render: PropTypes.func.isRequired // 必須接收一個 render 屬性,而且是函數}
const App = (props) => ( <div style={{ height: '500px' }}> <p>{props.a}</p> <Mouse render={ /* render 是一個函數組件 */ ({ x, y }) => <h1>The mouse position is ({x}, {y})</h1> }/>
</div>)
/** * 即,定義了 Mouse 組件,只有獲取 x y 的能力。 * 至於 Mouse 組件如何渲染,App 說了算,通過 render prop 的方式告訴 Mouse 。 */
export default App


相關焦點

  • 初中政治:知識點總結,有心的小同學,都在提前複習期末知識點了
    初中政治:知識點總結,有心的小同學,都在提前複習期末知識點了初中政治看教學內容確實簡單,都能看懂,為什麼考高分卻是不容易?有同學也說,我該背的都背了,為什麼拿不到分?在小編老師看來,初中政治相對簡單,涉及的知識點也不多。
  • 2021年中考數學知識點:概率知識點總結
    中考網整理了關於2021年中考數學知識點:概率知識點總結,希望對同學們有所幫助,僅供參考。   一、概率是事件A發生可能性的大小,這是概率的描述性定義。   如果存在一個實數p,當試驗次數n很大時,頻率穩定在p附近擺動,稱頻率的這個穩定值p為概率。這是概率的統計性定義。
  • 精通react/vue組件設計教你實現一個極具創意的加載(Loading)組件
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫前言本文是筆者寫組件設計的第八篇文章, 今天帶大家用5分鐘實現一個極具創意的加載(loading)組件.涉及的核心知識點主要是css3相關特性, 如果大家非常熟悉,可直接跳過介紹直接看正文
  • 耐克react跑鞋耐磨嗎 耐克react跑鞋壽命為多少km
    耐克的緩震科技react是一款能夠和阿迪達斯的boost相提並論的科技,耐克的react跑鞋也是非常受歡迎的鞋款,那麼,耐克的react跑鞋的耐磨性怎麼樣呢?跑鞋的壽命又是多少呢?感興趣的朋友一起來看看吧!
  • 「電影」在心理學中的知識點考查總結
    電影的製作原理在心理學中經常用來以例子的形式來進行考查,會涉及到很多知識點,接下來,小編就帶著大家來總結一下。1.感覺後效在刺激作用停止後暫時保留的感覺現象稱之為感覺後效,也叫感覺後像。看電影時一幅幅畫面以每秒24幀的速度放映,當前邊一幀畫面放過畫面還在我們眼前時,後面的畫面又飛速的來到,所以我們會覺得畫面是運動的,這就運用了感覺後效的規律。
  • 幾個非常有意思的javascript知識點總結
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫作為一名前端愛好者, 筆者利用空餘時間研究了幾個國外網站的源碼,發現不管是庫,還是業務代碼,都會用到了一些比較有意思的API,雖然平時在工作中部分接觸過,但是經過這次的研究,覺得很有必要總結一下,畢竟已經2020
  • 高中數學知識點總結:複數
    高中數學知識點總結:複數 2013-01-11 17:01 來源:新東方網整理 作者:
  • 高考複習:高中化學知識點總結,非常詳細的內容,值得列印學習
    高考化學複習:考試知識點、重點、關鍵點、解題技巧、高考真題等在我們的日常生活中,化學現象無處不在,在這些隨處可見的化學現象中,我們可以看到很多高中化學知識的應用。人們將化學知識運用到生活和生產中,便利了人們生活,促進了社會發展。
  • 黑馬程式設計師:Java運算符知識點總結
    下面一起來看看Java運算符知識點總結吧!看完了Java運算符知識點總結,想必大家對運算符已經有了一個基本的認識了。
  • 2020中考物理知識點總結:力和運動
    中考網整理了關於2020中考物理知識點總結:力和運動,希望對同學們有所幫助,僅供參考。   1.牛頓第一定律:一切物體在沒有受到外力作用的時候,總保持靜止狀態或勻速直線運動狀態。(牛頓第一定律是在經驗事實的基礎上,通過進一步的推理而概括出來的,因而不能用實驗來證明這一定律)。
  • 高二化學知識點總結,用它期末複習,期末成績考試成績80+
    高二化學知識點總結,用它期末複習,期末成績考試成績80+。(資料分享在文末)高中化學是文科性質非常濃重的學科,但凡成績不好的同學,基本上都是書上知識點掌握不牢。老師怎麼著急都沒有用,因為學生上課的時間記住了,下課不進行複習,馬上就會忘記,甚至會出現知識點「夾生」的情況。所以今天給大家推薦一套「高二化學知識點總結」,是最新整理的,基礎薄弱的同學可以進行對照記憶。再進行刷題總結經驗,期末考試成績提高20分應該不是問題。
  • 高中數學重點章節:函數基礎知識點梳理總結,複習必備
    ——莎士比亞每天分享高中學習方法、高分經驗、解題技巧等,幫助大家找到正確的學習方法去學習,今天給大家分享的是高中數學函數知識點歸納總結。函數知識點是高中數學學習的重要內容,也是高考出題中重點考查內容,試卷分數佔比很大,所以同學們要加強練習、重點掌握。
  • 初中數學知識點:二次函數知識點總結
    初中數學知識點:二次函數知識點總結 I.定義與定義表達式 一般地,自變量x和因變量y之間存在如下關係:y=ax^2+bx+c (a,b,c為常數,a≠0,且a決定函數的開口方向,a>0時,開口方向向上,a<0時,開口方向向下,IaI還可以決定開口大小,IaI越大開口就越小,
  • 精通react/vue組件設計之實現一個Tag(標籤)和Empty(空狀態)組件
    微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫前言本文是筆者寫組件設計的第五篇文章,之所以會寫組件設計相關的文章,是因為作為一名前端優秀的前端工程師,面對各種繁瑣而重複的工作,我們不應該按部就班的去"辛勤勞動",而是要根據已有前端的開發經驗,總結出一套自己的高效開發的方法
  • 都給你整理好了,高中歷史必修二知識點總結,拿走不謝!
    高中的學習時間很寶貴,與其讓學生從課堂筆記中整理出來知識點,不如老師按照《考試大綱》整理一份資料讓學生去複習。拿高中歷史必修二來說,老師在整理資料時,可以根據最近幾年的題型總結出高頻考點,讓學生重點記憶,這樣學習效率更高,學習效果越好。
  • 等差數列知識點及類型題總結,數學最重要的知識點之一!需搞懂
    也有不少同學沒有將這塊知識點搞懂,對此,這裡也給大家帶來了等差數列知識點及類型題總結,這是數學最重要的知識點之一!需搞懂才行需列印版請私信回復「100」!
  • 初中歷史知識點總結
    初中歷史知識點總結中國古代史部分一、元謀人北:P2目前我國境內已知最早的人類,是距今約170萬年的元謀人
  • 高考文綜必背:21頁,高中政治知識點總結,吃透輕鬆提分!
    高中政治是文綜科目中最容易拿高分的,但是很多同學忽略了這個科目,認為政治的學習很無聊,知識點繁雜,涉及的範圍也很廣,包括了經濟、政治、文化、哲學。哲學相對於其他三個來說是最難的一部分,在對哲學的理解上十分抽象,只要考試涉及到這部分內容,基本拿不到分。
  • 與阿迪的boost相比,耐克的新科技react怎麼樣?
    於是在這種強烈的危機感之下,Nike公司在去年推出了一項全新的科技——react,對其的要求定位在了和Adidas的看家技術boost同一高度上。和boost一樣,react作為一項全新的緩震技術,它的一次亮相也同樣選在了籃球鞋上。而且之後為了和boost爭奪市場,react同樣被Nike運用到了其他的運動鞋之上。react一經出世,就被很多朋友拿來和boost對比。
  • 高中物理:人教版必修一知識點總結+解題方法歸納!期末高考必備
    童鞋們好哇,馬上期末了哦,學姐最近發的資料也都是幫助童鞋們期末考試的總結性資料高中物理還是比較難搞的,知識點比較多,也考驗學生的羅輯思維,做題和知識點完全是兩種感覺,即使理論學會了,實踐做題也比較難所以學姐總結了高中物理:人教版必修一知識點總結+解題方法歸納!