首頁 > 軟體

React的事件處理你瞭解嗎

2022-03-09 10:00:41

一、React的事件處理

1、與DOM事件處理的不同之處

(1)React事件的命名方式:小駝峰方式,DOM的命名方式是小寫

例如:DOM的命名:onclick

React的命名:onClick

(2)事件處理常式是以物件的方式賦值,而不是以字串的方式賦值

例如:DOM以字串方式:onclick = "handleClick()"

React以物件方式:onClick = { handleClick }

(3)阻止預設事件的方式不同

DOM通過返回false來阻止: <a href="www.baidu.com" οnclick="javascript:return false;">百度</a>

React需要顯式呼叫e.preventDefault來阻止

2、React中事件處理常式的定義

(1)使用ES6的箭頭數

①在render函數中使用箭頭函數:

Ⅰ、優點:不用在建構函式中繫結this

Ⅱ、缺點:當函數的邏輯比較複雜時,render就顯得臃腫,無法直觀的看到元件的UI結構,程式碼可讀性差

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件處理常式-->在render中使用箭頭函數</title>
    <script src="../js/react.development.js"></script>
    <script src="../js/react-dom.development.js"></script>
    <script src="../js/babel.min.js"></script>
</head>
<body>
    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root');
        //1.建立一個類元件
        class MyComponent extends React.Component{
            constructor(props){
                super(props)
                this.state={
                    msg: '小森同學'
                }
            }
            render(){
                return (
                    <div>
                        <button onClick= { ()=>{ console.log(this.state.msg)} } >點我</button>
                    </div>
                )
            }
        }
        //2.進行渲染
        ReactDOM.render(<MyComponent/>,root)
    </script>
</body>
</html>

②使用class fields語法:將箭頭函數賦給類的屬性

Ⅰ、優點:不用在建構函式中繫結this,在render函數中呼叫簡單

<body>
    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root');
        //1.建立一個類元件
        class MyComponent extends React.Component{
            constructor(props){
                super(props)
                this.state={
                    msg: '小沈同學',
                    number: 0
                }
            }
            handleClick = ()=>{  //將箭頭函數賦給類的屬性
                console.log(this.state.msg)  //將一個箭頭函數賦值為handleClick,handleClick是MyComponent的一個屬性
            }
            render(){
                console.log('render')
                return (
                    <div>
                        <button onClick= { this.handleClick } >點我</button>  //呼叫這個屬性
                    </div>
                )
            }
        }
        //2.進行渲染
        ReactDOM.render(<MyComponent/>,root)
    </script>
</body>

(2)在建構函式中進行繫結:將事件處理常式作為類的成員函數

注意:在定義事件處理常式時,是無法識別this(即this是undefined的),必須在建構函式中繫結this

①、優點:在render函數呼叫時不需要重新建立事件處理常式

②、缺點:當事件處理很多時,建構函式就顯的很繁瑣

<body>
    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root');
        //1.建立一個類元件
        class MyComponent extends React.Component{
            constructor(props){
                super(props)
                this.state={
                    msg: '小沈同學',
                    number: 0
                }
                this.add = this.add.bind(this)  //this指標繫結到函數add裡面去
            }
            handleClick = ()=>{
                console.log(this.state.msg)
            }
            add(){  //如果上述不繫結this,那麼add函數裡的this將無法識別
                let num = this.state.number
                num++
                this.setState({
                    number: num
                })
                console.log(this.state.number)
            }
            render(){
                console.log('render')
                return (
                    <div>
                        <button onClick= { this.handleClick } >點我</button>
                        <button onClick= { this.add }>Number++</button>
                    </div>
                )
            }
        }
        //2.進行渲染
        ReactDOM.render(<MyComponent/>,root)
    </script>
</body>

(3)在render函數中繫結this

①、優點:在呼叫事件處理常式時,傳參比較方便

②、缺點:每次呼叫render函數時都重新系結,導致效能下降

<body>
    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root');
        //1.建立一個類元件
        class MyComponent extends React.Component{
            constructor(props){
                super(props)
                this.state={
                    msg: '小沈同學',
                    number: 0
                }
                // this.add = this.add.bind(this)  //this指標繫結到函數add裡面去
            }
            handleClick = ()=>{
                console.log(this.state.msg)
            }
            add(){  //如果上述不繫結this,那麼add函數裡的this將無法識別
                let num = this.state.number
                num++
                this.setState({
                    number: num
                })
                console.log(this.state.number)
            }
            render(){
                console.log('render')
                return (
                    <div>
                        <button onClick= { this.handleClick } >點我</button>
                        <button onClick= { this.add.bind(this) }>Number++</button>
                    </div>
                )
            }
        }
        //2.進行渲染
        ReactDOM.render(<MyComponent/>,root)
    </script>
</body>

(4)React中事件處理常式

幾種方式的比較

影響constructor函數中bind使用class fields語法render中使用箭頭函數render中使用bindrender時生成新函數否否是是效能無影響無影響有影響有影響可直接攜帶引數否否是是簡潔性不好好好好

(5)注意事項

①React事件的命名採用小駝峰式(camelCase),而不是純小寫。且事件名稱之後不能加(),否則會直接執行

②不能通過返回false的方式阻止預設行為,必須顯示的使用preventDefault

③必須謹慎對待JXS回撥函數中的this,在JavaScript中,class(類)的方法預設不會繫結this。如果忘記繫結this.textChange並把它傳入onChange,當呼叫這個函數的時候,this的值為undefined。如果覺得使用bind麻煩,還可以使用箭頭函數。

3、事件處理中的引數傳遞

(1)直接傳遞引數

①在建構函式中給事件處理常式繫結this,呼叫事件處理常式時直接傳參

 <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root');
        //1.定義類元件
        class Clock extends React.Component{
            constructor(props){
                super(props)
                this.state= {
                    list:[
                        {
                            id: 111,
                            msg: '小森'
                        },
                        {
                            id: 222,
                            msg: '小沈'
                        },
                        {
                            id: 333,
                            msg: '小顧'
                        }
                    ],
                    msg: '編號:'
                }
                this.handleClick = this.handleClick.bind(this)
            }
            handleClick(id){ //事件處理常式
                alert("編號:"+id)
            }
            render(){
                //獲取狀態屬性值
                const { list } = this.state 
                return (
                    <div>
                        {
                            list.map((item)=>
                               <button onClick={ ()=>{this.handleClick(item.id)}} key={item.id}>{item.msg}</button> 
                            )
                        }
                    </div>
                )
            }
        }
        //2.渲染
        ReactDOM.render(<Clock/>,root)
    </script>

注意:在箭頭函數中呼叫事件處理常式時不需要繫結this

②在render函數中呼叫事件處理常式時進行this的繫結

<div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root');
        //1.定義類元件
        class Clock extends React.Component{
            constructor(props){
                super(props)
                this.state= {
                    list:[
                        {
                            id: 111,
                            msg: '小森'
                        },
                        {
                            id: 222,
                            msg: '小沈'
                        },
                        {
                            id: 333,
                            msg: '小顧'
                        }
                    ],
                    msg: '編號:'
                }
            }
            handleClick(id){ //事件處理常式,e表示觸發事件的物件,成員函數
                let str = this.state.msg
                alert(str + id)
            }
            render(){
                //獲取狀態屬性值
                const { list } = this.state 
                return (
                    <div>
                        {
                            list.map((item)=>
                                <button onClick={ this.handleClick.bind(this,item.id) } key={item.id}>{ item.msg }</button>
                            )
                        }
                    </div>
                )
            }
        }
        //2.渲染
        ReactDOM.render(<Clock/>,root)
    </script>

(2)在定義UI控制元件時使用data自定義屬性,在事件處理常式中通過'e.target.dataset.屬性名'來獲取UI控制元件中的data屬性值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件處理中的引數傳遞</title>
    <script src="../js/react.development.js"></script>
    <script src="../js/react-dom.development.js"></script>
    <script src="../js/babel.min.js"></script>
</head>
<body>
    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root');
        //1.定義類元件
        class Clock extends React.Component{
            constructor(props){
                super(props)
                this.state= {
                    list:[
                        {
                            id: 111,
                            msg: '小森'
                        },
                        {
                            id: 222,
                            msg: '小沈'
                        },
                        {
                            id: 333,
                            msg: '小顧'
                        }
                    ],
                    msg: '編號:'
                }
            }
            handleClick(e){ //事件處理常式,e表示觸發事件的物件
                let str = this.state.msg
                alert(str + e.target.dataset.count)
                    //事件處理物件event,通過event可以得到target目標物件,就是那個button。dataset,得到自定義屬性的集合,在集合裡找到count
            }
            render(){
                //獲取狀態屬性值
                const { list } = this.state 
                return (
                    <div>
                        {
                            list.map((item)=>
                                  <button 
                                     onClick={ this.handleClick.bind(this) } 
                                     key={item.id}
                                     data-count = { item.id}  //標籤的自定義屬性用'data-'開頭後跟自定義屬性名
                                    >{ item.msg }</button>
                            )
                        }
                    </div>
                )
            }
        }
        //2.渲染
        ReactDOM.render(<Clock/>,root)
    </script>
</body>
</html>

4、事件流

(1)React的事件流預設是冒泡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件流</title>
    <script src="../js/react.development.js"></script>
    <script src="../js/react-dom.development.js"></script>
    <script src="../js/babel.min.js"></script>
</head>
<body>
    <div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root')
        //1.定義CSS樣式
        const style = {
            child: {
                width: '100px',
                height: '100px',
                backgroundColor: 'red'
            },
            parent: {
                width: '150px',
                height: '150px',
                backgroundColor: 'blue'
            },
            ancestor: {
                width: '200px',
                height: '200px',
                backgroundColor: 'green'
            }
        }
        //2.定義類元件
        class App extends React.Component{
            render(){
                return (
                    <div
                        onClick= { ()=>{ console.log('ancestor')}}
                        style = { style.ancestor }
                    >
                        <div
                           onClick={ ()=>{ console.log('parent')}}
                           style = { style.parent }
                        >
                            <div 
                               onClick={ (e)=>{ 
                                   console.log('child')
                                   e.stopPropagation() //阻止冒泡
                                }}
                               style = {style.child }
                            >
                            </div>
                        </div>
                    </div>
                )
            }
        }
        //3.渲染
        ReactDOM.render(<App/>,root)
    </script>
</body>
</html>
//輸出child,parent,ancestor

(2)React中使用捕獲方式:事件型別後面加一個字尾Capture

先由document找到最外層綠色的,然後傳給藍色,然後傳給紅色。所以工具中輸出的順序是(ancestor,parent,child)

5、事件物件

雖然React事件是合成事件,但是在事件處理中可以獲取事件物件的

(1)在React事件處理中有一個全域性事件物件

event物件,每次事件觸發後(事件處理常式呼叫完成後),就會清空event物件當下一次事件觸發時重新獲取該物件。該物件不是原生(DOM)的event物件,但是可以通過該物件獲取原生物件的部分屬性

<div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root')
        //1.定義樣式規則
        const style = {
            "mydiv": {
                width: '150px',
                height: '150px',
                backgroundColor: 'red'
            }
        }
        //2.定義類元件
        class App extends React.Component{
            constructor(props){
                super(props)
                this.state = {
                    x: 0,
                    y: 0
                }
            }
            render(){
                return (
                    <div>
                        <div style = { style['mydiv']}  //以陣列的方式設定樣式
                             onClick= { (event)=> { //'event'物件不是原生的event,但是可以通過event來獲取原生的事件物件的部分屬性
                                const { clientX,clientY } = event
                                 this.setState({
                                     x: event.clientX,
                                     y: event.clientY
                                 })
                        >
                          X: {this.state.x},Y: { this.state.y }
                        </div>
                    </div>
                )
            }
        }
        //3.渲染
        ReactDOM.render(<App />,root)
    </script>

(2)在非同步操作中獲取event

 問題:當事件觸發、響應結束後,event物件會被清空,但是非同步資料還沒有得到,在得到非同步資料之後再去存取 event物件的屬性就會報錯。

解決辦法:先將event物件的某些屬性值儲存起來,得到非同步資料之後再來使用這些屬性值

<div id="root"></div>
    <script type="text/babel">
        let root = document.getElementById('root')
        //1.定義樣式規則
        const style = {
            "mydiv": {
                width: '150px',
                height: '150px',
                backgroundColor: 'red'
            }
        }
        //2.定義類元件
        class App extends React.Component{
            constructor(props){
                super(props)
                this.state = {
                    x: 0,
                    y: 0
                }
            }
            render(){
                return (
                    <div>
                        <div style = { style['mydiv']}  //以陣列的方式設定樣式
                             onClick= { (event)=> { //'event'物件不是原生的event,但是可以通過event來獲取原生的事件物件的部分屬性
                                const { clientX,clientY } = event //定義變數,將event儲存起來
                                setTimeout(()=>{  //下次觸發時就可以得到儲存在變數中的值
                                    this.setState({
                                        x: clientX,
                                        y: clientY
                                    })
                                },1000)
                             }}
                        >
                          X: {this.state.x},Y: { this.state.y }
                        </div>
                    </div>
                )
            }
        }
        //3.渲染
        ReactDOM.render(<App />,root)
    </script>

總結

本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容! 


IT145.com E-mail:sddin#qq.com