好程式設計師web前端培訓分享React學習筆記(二)

好程式設計師發表於2020-04-26

  好程式設計師 web前端培訓分享 React學習筆記( 元件的資料掛載方式 屬性(props) props 是正常是外部傳入的,元件內部也可以透過一些方式來初始化的設定,屬性不能被元件自己更改,但是你可以透過父元件主動重新渲染的方式來傳入新的  props

   屬性是描述性質、特點的,元件自己不能隨意更改。

   之前的元件程式碼裡面有 props 的簡單使用,總的來說,在使用一個元件的時候,可以把引數放在標籤的屬性當中,所有的屬性都會作為元件  props  物件的鍵值。透過箭頭函式建立的元件,需要透過函式的引數來接收 props :

import   React,   {   Component,   Fragment   }   from   'react' import   ReactDOM   from   'react-dom' class   Title   extends   Component   {

   render   ()   {

     return   (

         < h1 > 歡迎進入{ this .props.name}的世界 < /h1>

     )

   }} const   Content   =   (props)   =>   {

   return   (

     < p > {props.name}是一個構建UI的庫 < /p>

   )} class   App   extends   Component   {

   render   ()   {

     return   (

         < Fragment >

         < Title   name = "React"   />

         < Content   name = "React.js"   />

       < /Fragment>

     )

   }} ReactDOM.render(

     < App /> ,

   document .getElementById( 'root' ))

設定元件的預設props

import   React,   {   Component,   Fragment   }   from   'react' import   ReactDOM   from   'react-dom' class   Title   extends   Component   {

   // 使用類建立的元件,直接在這裡寫static方法,建立defaultProps    static   defaultProps   =   {

     name :   'React'

   }

   render   ()   {

     return   (

         < h1 > 歡迎進入{ this .props.name}的世界 < /h1>

     )

   }} const   Content   =   (props)   =>   {

   return   (

     < p > {props.name}是一個構建UI的庫 < /p>

   )} // 使用箭頭函式建立的元件,需要在這個元件上直接寫defaultProps屬性 Content.defaultProps   =   {

   name :   'React.js' } class   App   extends   Component   {

   render   ()   {

     return   (

         < Fragment >

         { /* 由於設定了defaultProps, 不傳props也能正常執行,如果傳遞了就會覆蓋defaultProps的值 */ }

         < Title   />

         < Content   />

       < /Fragment>

     )

   }} ReactDOM.render(

     < App /> ,

   document .getElementById( 'root' ))

props.children

我們知道使用元件的時候,可以巢狀。要在自定義元件的使用巢狀結構,就需要使用  props.children  。在實際的工作當中,我們幾乎每天都需要用這種方式來編寫元件。

import   React,   {   Component,   Fragment   }   from   'react' import   ReactDOM   from   'react-dom' class   Title   extends   Component   {

   render   ()   {

     return   (

         < h1 > 歡迎進入{ this .props.children}的世界 < /h1>

     )

   }} const   Content   =   (props)   =>   {

   return   (

     < p > {props.children} < /p>

   )} class   App   extends   Component   {

   render   ()   {

     return   (

         < Fragment >

         < Title > React < /Title>

         < Content >< i > React.js < /i>是一個構建UI的庫</Content>

       < /Fragment>

     )

   }} ReactDOM.render(

     < App /> ,

   document .getElementById( 'root' ))

使用prop-types檢查props

React其實是為了構建大型應用程式而生, 在一個大型應用中,根本不知道別人使用你寫的元件的時候會傳入什麼樣的引數,有可能會造成應用程式執行不了,但是不報錯。為了解決這個問題,React提供了一種機制,讓寫元件的人可以給元件的 props 設定引數檢查,需要安裝和使用 prop-types :

$ npm i prop-types -S

狀態(state)

狀態就是元件描述某種顯示情況的資料,由元件自己設定和更改,也就是說由元件自己維護,使用狀態的目的就是為了在不同的狀態下使元件的顯示不同(自己管理)

定義state

第一種方式

import   React,   {   Component   }   from   'react' import   ReactDOM   from   'react-dom' class   App   extends   Component   {

   state   =   {

     name :   'React' ,

     isLiked :   false

   }

   render   ()   {

     return   (

       < div >

         < h1 > 歡迎來到{ this .state.name}的世界 < /h1>

         < button >

           {

             this .state.isLiked   ?   '❤️取消'   :   ' 收藏'

           }

         < /button>

       < /div>

     )

   }}ReactDOM.render(

     < App /> ,

   document .getElementById( 'root' ))

另一種方式(推薦)

import   React,   {   Component   }   from   'react' import   ReactDOM   from   'react-dom' class   App   extends   Component   {

   constructor()   {

     super ()

     this .state   =   {

       name :   'React' ,

       isLiked :   false

     }

   }

   render   ()   {

     return   (

         < div >

         < h1 > 歡迎來到{ this .state.name}的世界 < /h1>

         < button >

           {

             this .state.isLiked   ?   '❤️取消'   :   ' 收藏'

           }

         < /button>

       < /div>

     )

   }}ReactDOM.render(

   < App /> ,

   document .getElementById( 'root' ))

this.props this.state 是純js物件,在vue中,data屬性是利用 Object.defineProperty 處理過的,更改data的資料的時候會觸發資料的 getter setter ,但是React中沒有做這樣的處理,如果直接更改的話,react是無法得知的,所以,需要使用特殊的更改狀態的方法 setState

setState

isLiked  存放在例項的  state  物件當中,元件的  render  函式內,會根據元件的  state  的中的 isLiked 不同顯示“取消”或“收藏”內容。下面給  button  加上了點選的事件監聽。

import   React,   {   Component   }   from   'react' import   ReactDOM   from   'react-dom' class   App   extends   Component   {

   constructor()   {

     super ()

     this .state   =   {

       name :   'React' ,

       isLiked :   false

     }

   }

   handleBtnClick   =   ()   =>   {

     this .setState({

       isLiked :   !this .state.isLiked

     })

   }

   render   ()   {

     return   (

       < div >

         < h1 > 歡迎來到{ this .state.name}的世界 < /h1>

         < button   onClick = { this .handleBtnClick} >

           {

             this .state.isLiked   ?   '❤️取消'   :   ' 收藏'

           }

         < /button>

       < /div>

     )

   }}ReactDOM.render(

     < App /> ,

   document .getElementById( 'root' ))

setState 有兩個引數

第一個引數可以是物件,也可以是方法return一個物件,我們把這個引數叫做 updater

·  引數是物件

this .setState({

   isLiked :   !this .state.isLiked})

·  引數是方法

this.setState((prevState, props) => {

  return {

    isLiked: !prevState.isLiked

  }

})


注意的是這個方法接收兩個引數,第一個是上一次的state, 第二個是props

setState 是非同步的,所以想要獲取到最新的state,沒有辦法獲取,就有了第二個引數,這是一個可選的回撥函式

this .setState((prevState,   props)   =>   {

   return   {

     isLiked :   ! prevState.isLiked

   }},   ()   =>   {

   console.log( '回撥裡的' , this .state.isLiked)})console.log( 'setState外部的' , this .state.isLiked)

屬性vs狀態

相似點:

都是純js物件,都會觸發render更新,都具有確定性(狀態/屬性相同,結果相同)

不同點:

00001.  屬效能從父元件獲取,狀態不能

00002.  屬性可以由父元件修改,狀態不能

00003.  屬效能在內部設定預設值,狀態也可以

00004.  屬性不在元件內部修改,狀態要改

00005.  屬效能設定子元件初始值,狀態不可以

00006.  屬性可以修改子元件的值,狀態不可以

state  的主要作用是用於元件儲存、控制、修改自己的可變狀態。 state  在元件內部初始化,可以被元件自身修改,而外部不能訪問也不能修改。你可以認為  state  是一個區域性的、只能被元件自身控制的資料來源。 state  中狀態可以透過  this.setState 方法進行更新, setState  會導致元件的重新渲染。

props  的主要作用是讓使用該元件的父元件可以傳入引數來配置該元件。它是外部傳進來的配置引數,元件內部無法控制也無法修改。除非外部元件主動傳入新的  props ,否則元件的  props 永遠保持不變。

如果搞不清  state  和  props  的使用場景,記住一個簡單的規則: 儘量少地用  state ,多用  props

沒有  state  的元件叫無狀態元件(stateless component),設定了 state 的叫做有狀態元件(stateful component)。因為狀態會帶來管理的複雜性,我們儘量多地寫無狀態元件,儘量少地寫有狀態的元件。這樣會降低程式碼維護的難度,也會在一定程度上增強元件的可複用性。

##狀態提升

如果有多個元件共享一個資料,把這個資料放到共同的父級元件中來管理

受控元件與非受控元件

React元件的資料渲染是否被呼叫者傳遞的 props 完全控制,控制則為受控元件,否則非受控元件。

 

渲染資料

·  條件渲染

{

  condition   ?   '❤️取消'   :   ' 收藏' }

·  列表渲染

// 資料 const   people   =   [{

   id :   1 ,

   name :   'Leo' ,

   age :   35 },   {

   id :   2 ,

   name :   'XiaoMing' ,

   age :   16 }] // 渲染列表 {

   people.map(person   =>   {

     return   (

       < dl   key = {person.id} >

         < dt > {person.name} < /dt>

         < dd > age :   {person.age} < /dd>

       < /dl>

     )

   })}

React的高效依賴於所謂的 Virtual-DOM,儘量不碰 DOM。對於列表元素來說會有一個問題:元素可能會在一個列表中改變位置。要實現這個操作,只需要交換一下 DOM 位置就行了,但是React並不知道其實我們只是改變了元素的位置,所以它會重新渲染後面兩個元素(再執行 Virtual-DOM ),這樣會大大增加 DOM 操作。但如果給每個元素加上唯一的標識,React 就可以知道這兩個元素只是交換了位置,這個標識就是 key ,這個  key  必須是每個元素唯一的標識

·  dangerouslySetHTML

對於富文字建立的內容,後臺拿到的資料是這樣的:

content   =   "<p>React.js是一個構建UI的庫</p>"

處於安全的原因,React當中所有表示式的內容會被轉義,如果直接輸入,標籤會被當成文字。這時候就需要使用 dangerouslySetHTML 屬性,它允許我們動態設定 innerHTML

import   React,   {   Component   }   from   'react' import   ReactDOM   from   'react-dom' class   App   extends   Component   {

   constructor()   {

     super ()

     this .state   =   {

       content   :   "<p>React.js是一個構建UI的庫</p>"

     }

   }

   render   ()   {

     return   (

         < div

         // 注意這裡是兩個下下劃線 __html          dangerouslySetInnerHTML = {{__html :   this .state.content}}

       />

     )

   }}ReactDOM.render(

     < App /> ,

   document .getElementById( 'root' ))

事件處理

繫結事件

採用on+事件名的方式來繫結一個事件,注意,這裡和原生的事件是有區別的,原生的事件全是小寫 onclick , React裡的事件是駝峰 onClick React的事件並不是原生事件,而是合成事件

事件handler的寫法

·  直接在render裡寫行內的箭頭函式(不推薦)

·  在元件內使用箭頭函式定義一個方法(推薦)

·  直接在元件內定義一個非箭頭函式的方法,然後在render裡直接使用 > (不推薦)

·  直接在元件內定義一個非箭頭函式的方法,然後在constructor裡bind(this)(推薦)

Event 物件

和普通瀏覽器一樣,事件handler會被自動傳入一個  event  物件,這個物件和普通的瀏覽器  event  物件所包含的方法和屬性都基本一致。不同的是 React中的  event  物件並不是瀏覽器提供的,而是它自己內部所構建的。它同樣具有 event.stopPropagation event.preventDefault 這種常用的方法

事件的引數傳遞

·  render 裡呼叫方法的地方外面包一層箭頭函式

·  render 裡透過 this.handleEvent.bind(this, 引數) 這樣的方式來傳遞

·  透過 event 傳遞

·  比較推薦的是做一個子元件, 在父元件中定義方法,透過 props 傳遞到子元件中,然後在子元件件透過 this.props.method 來呼叫

##處理使用者輸入

import   React,   {   Component   }   from   'react' import   ReactDOM   from   'react-dom' class   App   extends   Component   {

   constructor()   {

     super ()

     this .state   =   {

       xing :   '' ,

       ming :   ''

     }

   }

   handleInputChange   =   (e)   =>   {

     this .setState({

       [e.target.name] :   e.target.value

     })

   }

   render   ()   {

     const   {

       xing,

       ming

     }   =   this .state

     return   (

         < div >

         < label >

           < span > :< /span>

           < input

             type = "text"

             name = "xing"

             value = {xing}

             onChange = { this .handleInputChange}

           />

         < /label>

         < label >

           < span > :< /span>

           < input

             type = "text"

             name = "ming"

             value = {ming}

             onChange = { this .handleInputChange}

           />

         < /label>

         < p > 歡迎您 :   {xing}{ming} < /p>

       < /div>

     )

   }}ReactDOM.render(

     < App /> ,

   document .getElementById( 'root' ))

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913864/viewspace-2688497/,如需轉載,請註明出處,否則將追究法律責任。

相關文章