日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React之組件的分類、使用,事件對象,this指向問題,修改狀態以及受控組件與非受控組件

作者:Gik99 更新時間: 2023-08-01 編程語言

React之組件的介紹、創建與使用,事件對象,this指向問題,修改狀態以及受控組件與非受控組件

  • 一、組件基本介紹
  • 二、組件創建
    • 2.1 函數組件
    • 2.2 類組件
  • 三、將組件提取到單獨的js文件中
  • 四、有狀態組件和無狀態組件
  • 五、類組件的狀態
  • 六、事件處理
    • 6.1 注冊事件
    • 6.2 事件對象
    • 6.3 this指向問題
    • 6.4 this指向解決方案
  • 七、setState 修改狀態
  • 八、react核心理念(狀態不可變)
  • 九、表單處理
    • 9.1 受控組件
    • 9.2 非受控組件-ref

一、組件基本介紹

  • 組件是 React 開發(現代前端開發)中最重要的內容
  • 組件允許你將 UI 拆分為獨立、可復用的部分,每個部分都可以獨立的思考
  • 組合多個組件(組裝樂高積木)實現完整的頁面功能
  • 特點:獨立、可復用、可組合
  • 組件包含三部分:HTML/CSS/JS
  • 展示頁面中的可復用部分

二、組件創建

2.1 函數組件

  • 函數組件:使用JS的函數或者箭頭函數創建的組件
    • 使用 JS 的函數(或箭頭函數)創建的組件,叫做函數組件
    • 約定1:函數名稱必須以大寫字母開頭,React 據此區分組件和普通的 HTML標簽
    • 約定2:函數組件必須有返回值,表示該組件的 UI 結構;如果不需要渲染任何內容,則返回 null
  • 使用函數創建組件
// 使用普通函數創建組件:
function Hello() {
  return <div>這是我的第一個函數組件!</div>
}
function Button() {
  return <button>按鈕</button>
}

// 使用箭頭函數創建組件:
const Hello = () => <div>這是我的第一個函數組件!</div>
  • 使用組件
    • 組件就像 HTML 標簽一樣可以被渲染到頁面中。組件表示的是一段結構內容,對于函數組件來說,渲染的內容是函數返回值對應的內容
    • 使用函數名稱作為組件標簽名稱
// 使用 雙標簽 渲染組件:
<Hello></Hello>
ReactDOM.render(<Hello></Hello>, root)

// 使用 單標簽 渲染組件:
<Hello />
ReactDOM.createRoot(document.querySelector('#root')).render(<Hello></Hello>)

小結

  1. 在react中可以使用函數或者箭頭函數創建組件
  2. 組件的首字母必須大寫

2.2 類組件

內容

  • 使用 ES6 的 class 創建的組件,叫做類(class)組件
  • 約定1:類名稱也必須以大寫字母開頭
  • 約定2:類組件應該繼承 React.Component 父類,從而使用父類中提供的方法或屬性
  • 約定3:類組件必須提供 render 方法
  • 約定4:render 方法必須有返回值,表示該組件的 UI 結構

定義組件

// 導入 React
import React from 'react'
class Hello extends React.Component {
  render() {
    return <div>Hello Class Component!</div> 
  }
}
ReactDOM.render(<Hello />, root)

// 只導入 Component
import { Component } from 'react'
class Hello extends Component {
  render() {
    return <div>Hello Class Component!</div> 
  }
}

使用組件

ReactDOM.createRoot(document.querySelector('#root')).render(<Hello></Hello>)

總結

  1. 使用class語法創建組件比函數創建稍微麻煩一些,但是類組件的功能會比函數組件的功能更加強大(hooks 之前

三、將組件提取到單獨的js文件中

實現方式

  1. 創建 Hello.js
  2. 創建組件(函數 或 類)
  3. 在 Hello.js 中導出該組件
  4. 在 index.js 中導入 Hello 組件
  5. 渲染組件

核心代碼

// index.js
//直接導入
import Hello from './Hello'

//按需導入
// import {Hello} from './Hello'

// 渲染導入的Hello組件
ReactDOM.createRoot(document.querySelector('#root')).render(<Hello></Hello>)


// Hello.js
import { Component } from 'react'
class Hello extends Component {
  render() {
    return <div>Hello Class Component!</div>
  }
}
// 導出Hello組件(默認導出)
export default Hello

//按需導出
// export {
//	Hello
// }

四、有狀態組件和無狀態組件

內容

  • 函數組件又叫做無狀態組件 函數組件是不能自己提供數據【前提:不考慮 hooks 的情況下】
  • 類組件又叫做有狀態組件 類組件可以自己提供數據
  • 狀態state是組件的私有數據,當組件的狀態發生了改變,頁面結構也就發生了改變(數據驅動視圖
  • 函數組件是沒有狀態的,只負責頁面的展示態,不會發生變化),性能比較高
  • 類組件有自己的狀態,負責更新UI,只要類組件的數據發生了改變,UI 就會發生更新態)
  • 在項目中,一般都是由函數組件和類組件共同配合來完成的

比如計數器案例,點擊按鈕讓數值+1, 0和1就是不同時刻的狀態,當狀態從0變成1之后,UI也要跟著發生變化。React想要實現這種功能,就需要使用有狀態組件來完成。

  • 函數組件和類組件的區別:有沒有狀態【前提:不考慮 hooks 的情況下】

五、類組件的狀態

內容

  • 狀態state,即數據,是組件內部的私有數據,只能在組件內部使用
  • 狀態 state 的值是對象,表示一個組件中可以有多個數據
  • 通過 this.state.xxx 來獲取狀態

核心代碼

  • 創建 state
class Hello extends Component {
  // 為組件提供狀態
  state = {
    count: 0,
    list: [],
    isLoading: true
  }

  render() {
    return (
      <div>計數器</div>
    )
  }
}
  • 讀取狀態:通過 this.state 來獲取狀態
class Hello extends Component {
  // ...
  render() {
    // 通過 this.state 來訪問類組件的狀態
    return (
      <div>計數器:{this.state.count}</div>
    )
  }
}

六、事件處理

6.1 注冊事件

內容

  • React注冊事件與DOM的事件語法非常像

  • 語法on+事件名 ={事件處理程序} 比如onClick={this.handleClick}

  • 注意:React事件采用駝峰命名法,比如onMouseEnter, onClick

核心代碼

class App extends React.Component {
  handleClick() {
    console.log('點擊事件觸發')
  }
  
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>點我</button>
      </div>
    )
  }
}

6.2 事件對象

核心代碼

  • 可以通過事件處理程序的參數獲取到事件對象
  • 注意:React 中的事件對象是 React 內部處理后的事件對象,一般稱為:SyntheticBaseEvent 合成事件對象。用法與 DOM 原生的事件對象用法基本一致
function handleClick(e) {
  e.preventDefault()
  console.log('事件對象', e)
}

<a onClick={this.handleClick}>點我,不會跳轉頁面</a>

6.3 this指向問題

內容:

  • 事件處理程序中的this指向的是undefined

  • render方法中的this指向的是當前react組件。只有事件處理程序中的this有問題

  • 原因

    • 事件處理程序的函數式函數調用模式,在嚴格模式下,this指向undefined
    • render函數是被組件實例調用的,因此render函數中的this指向當前組件
class App extends React.Component {
  state = {
    msg: 'hello react'
  }
  handleClick() {
    console.log(this.state.msg)
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>點我</button>
      </div>
    )
  }
}

總結

  1. 在react的事件處理函數中,this指向undefined

6.4 this指向解決方案

內容

  • 解決事件處理程序中this指向問題主要有三種方式

  • 方式1:箭頭函數

class App extends React.Component {
  state = {
    msg: 'hello react'
  }
  handleClick() {
    console.log(this.state.msg)
  }
  render() {
    return (
      <div>
        <button onClick={() => this.handleClick()}>點我</button>
      </div>
    )
  }
}
  • 方式2:bind
class App extends React.Component {
  state = {
    msg: 'hello react'
  }
  handleClick() {
    console.log(this.state.msg)
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick.bind(this)}>點我</button>
      </div>
    )
  }
}
  • 方式3:箭頭函數形式的實例方法 - 推薦使用
class App extends React.Component {
  state = {
    msg: 'hello react'
  }

  handleClick = () => {
    console.log(this.state.msg)
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>點我</button>
      </div>
    )
  }
}

總結

  1. 推薦使用方式3,箭頭函數形式的實例方法
  • 解釋為什么方式3可以解決 this 指向問題:
// ES6
class Person1 {
  // 類的 構造函數
  constructor() {
    // 構造函數中的 this 就是實例對象
    console.log(this)
    this.name = 'jack'
    this.fn = () => {
      console.log(this)
    }
  }

  // 上述寫法簡化語法:
  // name = 'jack'
  // fn = () => {}

  // 這個形式的方法會被添加到原型中
  sayHi() {}
}

說明:

fn = () => {}  這種形式的語法是簡化語法(語法糖),書寫會更簡單。實際上,完整的寫法是:

constructor() {
  this.fn = () => {}
}

即:在構造函數中,給 this 添加了一個方法 fn

為什么可以解決 this 指向問題呢?
因為 constructor 中創建的箭頭函數,內部的 this 會指向 constructor 中的 this
而 constructor 中的 this 就是實例對象(也就是我們需要的 this

七、setState 修改狀態

內容

  • 語法:this.setState({ 要修改的部分數據 })
  • setState() 作用:1 修改 state 2 更新 UI
  • 思想:數據驅動視圖,也就是只需要修改數據(狀態)那么頁面(視圖)就會自動刷新
    • 核心:數據?。。?/li>
    • 從現在開始,我們關心的是如何修改數據,而不再是關心如何修改DOM
    • 并且,注意:盡量避免直接手動 DOM(通過 document.querySelector() 獲取到到DOM對象然后再操作) 操作?。。?/li>
  • 注意:不要直接修改 state 中的值,這是無效的

核心代碼

class Hello extends Component {
  state = {
    count: 0
  }

	handleClick = () => {
    this.setState({
      count: 10
    })
  }  

  render() {
    return (
      <div>
        <h1>計數器:{this.state.count}</h1>
        <button onClick={this.handleClick}>+1</button>
      </div>
    )
  }
}

// 在 count 當前值的基礎上加 1
this.setState({
  count: this.state.count + 10
})

總結

  1. 能直接修改 state 的值嗎?不能
  2. 如何修改 React 組件中的狀態?setState()
  3. setState 是哪來的?從 Component 父類繼承過來的

八、react核心理念(狀態不可變)

內容:

  • 狀態不可變指的是:不要直接修改狀態的值,而是基于當前狀態創建新的狀態值

核心代碼

state = {
  count: 0,
  list: [1, 2, 3],
  person: {
    name: 'jack',
    age: 18
  }
}

// 【不推薦】直接修改當前值的操作:
this.state.count++
++this.state.count
this.state.count += 1
this.state.count = 1

// 只要是數組中直接修改當前數組的方法都不能用!
this.state.list.push(123)

this.state.person.name = 'rose'

// 【推薦】不是直接修改當前值,而是創建新值的操作:
this.setState({
  count: this.state.count + 1,
  list: [...this.state.list, 123],
  person: {
    ...this.state.person,
    // 要修改的屬性,會覆蓋原來的屬性,這樣,就可以達到修改對象中屬性的目的了
    name: 'rose'
  }
})

九、表單處理

9.1 受控組件

內容

  • HTML中表單元素是可輸入的,即表單元素維護著自己的可變狀態(value)
  • 但是在react中,可變狀態通常是保存在state中的,并且要求狀態只能通過setState進行修改
  • React中將state中的數據與表單元素的value值綁定到了一起,由state的值來控制表單元素的值
  • 受控組件:value值受到了react狀態控制的表單元素

核心代碼:

class App extends React.Component {
  state = {
    msg: 'hello react'
  }

  handleChange = (e) => {
    this.setState({
      msg: e.target.value
    })
  }

  render() {
    return (
      <div>
        <input type="text" value={this.state.msg} onChange={this.handleChange}/>
      </div>
    )
  }
}

總結

  1. 使用受控組件的方式處理表單元素后,狀態的值就是表單元素的值。即:想要操作表單元素的值,只需要操作對應的狀態即可*

9.2 非受控組件-ref

非受控組件借助于ref,使用原生DOM的方式來獲取表單元素的值
內容

  • 受控組件是通過 React 組件的狀態來控制表單元素的值
  • 非受控組件是通過手動操作 DOM 的方式來控制
  • 此時,需要用到一個新的概念:ref
  • ref:用來在 React 中獲取 DOM 元素

核心代碼

// 1 導入 createRef 函數( 用來創建 ref 對象 )
import { createRef } from 'react'

class Hello extends Component {
  // 2 調用 createRef 函數來創建一個 ref 對象
  //   ref 對象的名稱(txtRef)可以是任意值
  //   命名要規范: txt(DOM 元素的自己標識) + Ref
  txtRef = createRef()

  handleClick = () => {
    // 文本框對應的 DOM 元素
    // console.log(this.txtRef.current)

    // 4 獲取文本框的值:
    console.log(this.txtRef.current.value)
  }

  render() {
    return (
      <div>
        {/*
        	3 將創建好的 ref 對象,設置為 input 標簽的 ref 屬性值
        		作用:將 ref 和 input DOM 綁定到一起,將來在通過 this.txtRef 拿到的就是當前 DOM 對象
        */}
        <input ref={this.txtRef} />
        <button onClick={this.handleClick}>獲取文本框的值</button>
      </div>
    )
  }
}

原文鏈接:https://blog.csdn.net/Gik99/article/details/131870685

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新