<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          React 組件中的事件處理、組件(受控、非受控)、函數柯里化

          2021-9-14    前端達人

          事件處理

          在React中獲取虛擬組件中的標簽的值

          1. 使用組件的 refs屬性
          2. 在虛擬組件的標簽中定義事件,在事件中通過 箭頭函數 獲取標簽的值
          3. 使用事件對象——event

          事件處理:

          • 通過onXxx屬性指定事件處理函數(注意大小寫)
            • React使用的是自定義(合成)事件, 而不是使用的原生DOM事件 ———為了更好的兼容性
            • React中的事件是通過事件委托方式處理的(委托給組件最外層的元素) ————為了高效
          • 通過event.target得到發生事件的DOM元素對象 ———不要過度使用ref

          使用event.target屬性:

          //創建組件 class Demo extends React.Component{ myRef = React.createRef() //展示輸入框的數據 showData = (event)=>{ alert(event.target.value); } render(){ return( <div> <input onBlur={this.showData} type="text" placeholder="失去焦點提示數據"/> </div> ) } } //渲染組件到頁面 ReactDOM.render(<Demo/>,document.getElementById('test')) 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18

          React事件處理和Dom事件處理區別:

          1、在 語法 上的不同點:

          • React事件名采用駝峰命名法,即事件名首字母大寫。如onclick(Dom)——onClick(React)

          • 響應事件的函數在React中以 對象方式 賦值,Dom是以 字符串方式 賦值

            <button onclick= ' clickMe( ) '>提交</button> ——Dom方式 <button onClick={ clickMe( ) }>提交</button> ——React方式 
                    
            • 1
            • 2

          2、在阻止事件的默認行為有區別:React事件是合成的,DOM事件是原生

          • Dom:返回false
          • React:顯示的調用事件對象event.preventDefault

          React事件處理函數

          • 1、使用ES6的箭頭函數

            class MyComponent extends React.Component{ constructor(props){ super(props); this.state={ number:0 } handleClick=()=>{ ++this.state.number; console.log(this.state.number); } render(){ return( <div> <button type='button' onClick={this.handleClick}>點我</button> </div> ) } } ReactDOM.render(<MyComponent/>,document.getElementById('example')); 
                    
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
          • 2、在組件中定義事件處理函數

            class MyComponent extends React.Component{ constructor(props){ super(props); this.state={ number:0 } this.handleClick=this.handleClick.bind(this); } handleClick(){ ++this.state.number; console.log(this.state.number); } render(){ return( <div> <button type='button' onClick={this.handleClick}>點我</button> </div> ) } } ReactDOM.render(<MyComponent/>,document.getElementById('example')); 
                    
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 注:這種方法的好處是每次render渲染都不會重新創建一個回調函數,沒有額外的性能損失,但是如果在一個組件中有很多的事件函數時這種在構造函數中綁定this的方法會顯得繁瑣
          • 3、在給事件賦值時綁定this

            class MyComponent extends React.Component{ constructor(props){ super(props); this.state={ number:0 } } handleClick(){ ++this.state.number; console.log(this.state.number); } render(){ return( <div> <button type='button' onClick={this.handleClick.bind(this)}>點我</button> </div> ) } } ReactDOM.render(<MyComponent/>,document.getElementById('example')); 
                    
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 注:但是此方法在每次render時都會重新創建一個新的函數,性能有一定的損失,但在事件處理函數需要傳參數時,這種方法就比較好

          事件流

          在該示例中,3個div嵌套顯示,并且每個元素上均綁定onClick事件。當用戶點擊紅色區域的div元素時,可以看到,控制臺先后輸出了child -> parent -> ancestor,這是因為在React的事件處理系統中,默認的事件流就是冒泡。

          const style={ child:{ width:'100px', height:'100px', background:'red' }, parent:{ width:'150px', height:'150px', background:'blue' }, ancestor:{ width:'200px', height:'200px', background:'green' } } class Example extends React.Component{ render(){ return( <div onClickCapture={()=> console.log('ancestor')} style={style.ancestor}> <div onClickCapture={ ()=> console.log('parent')} style={style.parent}> <div onClickCapture={ ()=> console.log('child')} style={style.child}></div> </div> </div> ) } } ReactDOM.render(<Example/>,document.getElementById('example')); 
          
          • 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

          在這里插入圖片描述

          • React默認的事件觸發方式:冒泡方式
          • 若將事件觸發改為捕獲方式:需要在事件名后帶上 Capture 后綴
          <div onClickCapture={()=> console.log('ancestor')} style={style.ancestor}> <div onClickCapture={ ()=> console.log('parent')} style={style.parent}> <div onClickCapture={ ()=> console.log('child')} style={style.child}></div> </div> </div> 
          
          • 1
          • 2
          • 3
          • 4
          • 5

          事件委托

          在合成事件系統中,所有的事件都是綁定在document元素上,即雖然在某個React元素上綁定了事件,但是,最后事件都委托給document統一觸發。因此,在合成事件中只能阻止合成事件中的事件傳播

          React 阻止的事件流,并沒有阻止真正DOM元素的事件觸發,還是按照冒泡的方式,層層將事件交給上級元素進行處理,最后事件傳播到docuement,觸發合成事件,在合成事件中,child觸發時,e.stopPropagation() 被調用,合成事件中的事件被終止。因此,合成事件中的stopPropagation無法阻止事件在真正元素上的傳遞,它只阻止合成事件中的事件流。相反,如果綁定一個真正的事件,那么,合成事件則會被終止。

          • 默認事件流是冒泡的,所有事件統一由document觸發,在React中阻止冒泡方法是調用e.stopPropagation()
          • React的合成事件是可以找到原生的事件對象
          • React中的合成事件中只有一個全局對象event,該對象不是原生的event,但通過它可以獲得event對象的部分屬性。每個事件觸發完后React的全局對象event就會被清空,因此不能在異步操作使用

          事件類型:
          在這里插入圖片描述

          收集表單數據

          非受控組件

          表單數據由DOM本身處理。即不受setState()的控制,與傳統的HTML表單輸入相似,input輸入值即顯示最新值(使用 ref 從DOM獲取表單值),即不受React控制改變表單元素提交的值的方式,稱為:“非受控組件”

          class Login extends React.Component{ handleSubmit = (event)=>{ event.preventDefault() //阻止表單提交 const {username,password} = this alert(`你輸入的用戶名是:${username.value},你輸入的密碼是:${password.value}`) } render(){ return( <form onSubmit={this.handleSubmit}> 用戶名:<input ref={c => this.username = c} type="text" name="username"/> 密碼:<input ref={c => this.password = c} type="password" name="password"/> <button>登錄</button> </form> ) } } //渲染組件 ReactDOM.render(<Login/>,document.getElementById('test')) 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18

          受控組件

          在HTML中,標簽<input>、<textarea><select>的值的改變通常是根據用戶輸入進行更新。在React中,可變狀態通常保存在組件的狀態屬性中,并且只能使用 setState() 更新,而呈現表單的React組件也控制著在后續用戶輸入時該表單中發生的情況,以這種由React控制的輸入表單元素而改變其值的方式,稱為:“受控組件”。

          class Login extends React.Component{ //初始化狀態 state = { username:'', //用戶名 password:'' //密碼 } //保存用戶名到狀態中 saveUsername = (event)=>{ this.setState({username:event.target.value}) } //保存密碼到狀態中 savePassword = (event)=>{ this.setState({password:event.target.value}) } //表單提交的回調 handleSubmit = (event)=>{ event.preventDefault() //阻止表單提交 const {username,password} = this.state alert(`你輸入的用戶名是:${username},你輸入的密碼是:${password}`) } render(){ return( <form onSubmit={this.handleSubmit}> 用戶名:<input onChange={this.saveUsername} type="text" name="username"/> 密碼:<input onChange={this.savePassword} type="password" name="password"/> <button>登錄</button> </form> ) } } //渲染組件 ReactDOM.render(<Login/>,document.getElementById('test')) 
          
          • 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

          受控和非受控元素都有其優點,根據具體情況選擇

          特征 非受控制 受控
          一次性檢索(例如表單提交)
          及時驗證 ×
          有條件的禁用提交按鈕 ×
          執行輸入格式 ×
          一個數據的幾個輸入 ×
          動態輸入 ×

          函數柯里化

          高階函數:如果一個函數符合下面2個規范中的任何一個,那該函數就是高階函數。

          1. 若A函數,接收的參數是一個函數,那么A就可以稱之為高階函數
          2. 若A函數,調用的返回值依然是一個函數,那么A就可以稱之為高階函數

          常見的高階函數有:Promise、setTimeout、arr.map()等等

          函數的柯里化:通過函數調用繼續返回函數的方式,實現多次接收參數最后統一處理的函數編碼形式。

          function sum(a){ return(b)=>{ return (c)=>{ return a+b+c } } } 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7

          函數柯里化的實現

          class Login extends React.Component{ //初始化狀態 state = { username:'', //用戶名 password:'' //密碼 } //保存表單數據到狀態中 saveFormData = (dataType)=>{ return (event)=>{ this.setState({[dataType]:event.target.value}) } } //表單提交的回調 handleSubmit = (event)=>{ event.preventDefault() //阻止表單提交 const {username,password} = this.state alert(`你輸入的用戶名是:${username},你輸入的密碼是:${password}`) } render(){ return( <form onSubmit={this.handleSubmit}> 用戶名:<input onChange={this.saveFormData('username')} type="text" name="username"/> 密碼:<input onChange={this.saveFormData('password')} type="password" name="password"/> <button>登錄</button> </form> ) } } //渲染組件 ReactDOM.render(<Login/>,document.getElementById('test')) 
          
          • 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



























          
          
          
          
          
          
          
          
          
          
          
          

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          轉自:csdn 免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合