從零開始學React:二檔 React生命週期以及組件開發

手挽手帶你學React入門二檔,組件開發的開始,合理運用生命週期和組件,可以讓你的開發變地流利又happy,這篇文章帶你學會建立組件,運用組建。學起來吧!javascript

視頻教程

React 組件生命週期

學習React,生命週期很重要,咱們瞭解完生命週期的各個組件,對寫高性能組件會有很大的幫助. 咱們先來看一張圖vue

組件初始化的時候java

一、getDefaultProps()node

設置默認的props,也能夠用dufaultProps設置組件的默認屬性.react

二、getInitialState()es6

在使用es6的class語法時是沒有這個鉤子函數的,能夠直接在constructor中定義this.state。此時能夠訪問this.props算法

三、componentWillMount()redux

組件初始化時只調用,之後組件更新不調用,整個生命週期只調用一次,此時能夠修改state。數組

四、 render()性能優化

react最重要的步驟,建立虛擬dom,進行diff算法,更新dom樹都在此進行。此時就不能更改state了。

五、componentDidMount()

組件渲染以後調用,只調用一次。

組件更新的時候 六、componentWillReceiveProps(nextProps)

組件初始化時不調用,組件接受新的props時調用。

七、shouldComponentUpdate(nextProps, nextState)

react性能優化很是重要的一環。組件接受新的state或者props時調用,咱們能夠設置在此對比先後兩個props和state是否相同,若是相同則返回false阻止更新,由於相同的屬性狀態必定會生成相同的dom樹,這樣就不須要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤爲是在dom結構複雜的時候

八、componentWillUpdata(nextProps, nextState)

組件初始化時不調用,只有在組件將要更新時才調用,此時能夠修改state,render 的時候會用你更改的值,可是這裏面不能調用 this.setState(),會讓你陷入死循環

九、render()

組件渲染

十、componentDidUpdate()

組件初始化時不調用,組件更新完成後調用,此時能夠獲取dom節點。

組件卸載的時候

十一、componentWillUnmount()

組件將要卸載時調用,一些事件監聽和定時器須要在此時清除。

// 在咱們組件第一次加載完的時候會這樣執行生命週期
export default class App extends Component {
    constructor(){
        super()
        this.state={
        
        }
    }

    // getDefaultProps(){
    // es6 不支持這個
    // console.log('1.執行getDefaultProps')
    // 具體用法在下面
    // }
    
    // getInitialState(){
    // es6裏不用它了
    // console.log('2.執行getInitialState')
    // 這個其實是上面的state 在 constructor實現
    // }
    componentWillMount(){
        console.log('3.執行componentWillMount')
    }
    render() {
        console.log('4.執行render')
        return (
            
        )
    }
    componentDidMount(){
        console.log('5.執行componentWillMount')

    }
}

// 接 getDefaultProps
// 在ES6裏這麼玩

// 還有一種玩法是ES7裏面的
// static defaultProps = {
 // name: 'demo'
 // }; 這裏咱們很少講了。。講多了該暈了 感興趣的加我微信 shouzi_1994
App.defaultProps = {
    name: 'demo'
};
複製代碼
// 在咱們組件更新的時候咱們進行以下生命週期
export default class App extends Component {
    constructor(){
        super()
        this.state={
            name:'test'
        }
    }
    componentWillReceiveProps(nextProps){
        // props 更新的時候調用
        console.log('1.執行componentWillReceiveProps')
    }
    shouldComponentUpdate(nextProps, nextState){
        console.log('2.執行shouldComponentUpdate')
        // 這個須要着重強調,咱們優化性能用它很重要!若是咱們即將更新的東西和原來的數據相同,return一個false就中止組件更新節約性能
        if(nextState.name == this.state.name){
            return false
        }else{
            return true
        }
    }
    componentWillMount(nextProps, nextState){
        // 在組件渲染前 調用這個
        console.log('3.執行componentWillMount')
    }
    change=()=>{
        this.setState({name:'QM'})
    }
    render() {
        console.log('4.執行render')
        return (
            <button onClick={this.change}>測試</button>
        )
    }
   componentDidUpdate(){
        console.log('5.執行componentDidUpdate')       
   }
   componentWillUnmount(){
    // 這個在卸載的時候會調用 業務邏輯寫裏面就行了 
   }
}
複製代碼

生命週期簡單介紹就這些了,真正工做中要根據業務需求來調用,大大增長你的開發效率,處理你開發中遇到的難題。

組件建立

其實咱們前面的App實際上就是一個組件了,咱們類比到vue裏面,它就是腳手架爲咱們建立的App.vue 是一個根組件,咱們別的組件都渲染到這個組件的內部就行了。

那麼 咱們如何建立一個子組件呢?

export default class App extends Component {
    constructor(){
        super()
        this.state={
        
        }
    }
  
    render() {
        //要想使用子組件也很簡單 用標籤的形式拿進來就行了
        return (
            <Children /> ) } } //下面咱們再寫一個class 而且繼承 Component 這就是一個組件了 class Children extends Component{ constructor(){ super() this.state={ } } render(){ return( <h1>我是子組件</h1> ) } } 複製代碼

組件傳參

咱們學會了如何建立組件,那麼組件怎麼傳參呢?這個是很是重要的東西,畢竟組件之間不能通信,那就沒有建立它的意義了。

父子傳參

在React中父子傳參極其相似Vue 直接在標籤上填寫屬性,可是在子組件接收的時候會有所不一樣

咱們接着使用上面的代碼

export default class App extends Component {
    constructor(){
        super()
        this.state={
        
        }
    }
  
    render() {
        //要想使用子組件也很簡單 用標籤的形式拿進來就行了
        return (
            <Children params={"我從父組件傳過來"}/> ) } } //下面咱們再寫一個class 而且繼承 Component 這就是一個組件了 class Children extends Component{ constructor(){ super() this.state={ } } // 經過這種形式 咱們就能夠把父組件的東西傳遞給子組件了,全部的屬性存儲在props裏面,上面咱們介紹生命週期的時候,也提了一下如何建立默認props。這裏咱們寫一下 render(){ return( <div> <h1>我是子組件</h1> <h2>{this.props.params}</h2> </div> ) } // 若是父組件沒有傳遞 params 咱們又想使用默認的props 那麼就要使用下面的寫法 } Children.defaultProps = { params: '我是默認的東西' }; // 設置了默認props之後 若是咱們不傳參就會默認展現咱們默認規定好的屬性了 複製代碼

插槽(相似Vue solt) 爲何要把插槽放在這裏講解呢?實際上React的插槽是經過傳參的形式下來的,怎麼理解呢?我以爲放進代碼中是最容易理解的。

export default class App extends Component {
    constructor(){
        super()
        this.state={
        
        }
    }
  
    render() {
        //要想使用子組件也很簡單 用標籤的形式拿進來就行了
        return (
            <Children params={"我從父組件傳過來"}> <div>傳遞第一個</div> <div>傳遞第二個</div> <div>傳遞第三個</div> </Children>
        )
    }
  
}

//下面咱們再寫一個class 而且繼承 Component 這就是一個組件了

class Children extends Component{
    constructor(){
        super()
        this.state={
        
        }
    }
    // 經過這種形式 咱們就能夠把父組件的東西傳遞給子組件了,全部的屬性存儲在props裏面,上面咱們介紹生命週期的時候,也提了一下如何建立默認props。這裏咱們寫一下

    render(){
        console.log(this.props)
        // {children:Array(3)
        // params:"我從父組件傳過來"}


        // children的內容爲 [
            // {$$typeof: Symbol(react.element), type: "div", key: null, ref: null, props: {…}, …},
            // {$$typeof: Symbol(react.element), type: "div", key: null, ref: null, props: {…}, …},
            // {$$typeof: Symbol(react.element), type: "div", key: null, ref: null, props: {…}, …}
            // ]
        //咱們能夠看到 他們被順序放到了 this.props.children中 而且 這是個數組 內部存儲的就是虛擬dom
        
        return(
            <div> <h1>我是子組件</h1> {/* 這裏我用循環的方式把三個children取出來直接渲染便可 */} {this.props.children.map((item,key)=>{ return item })} {/* 咱們更加直觀一點 */} {this.props.children[1]} {this.props.children[0]} {this.props.children[2]} {/* 看到這裏你們應該能夠知道插槽的簡單用法了吧 */} </div>
        )
    }
    // 若是父組件沒有傳遞 params 咱們又想使用默認的props 那麼就要使用下面的寫法
}

Children.defaultProps = {
    params: '我是默認的東西'
};

複製代碼

子傳父參 在Vue中咱們能夠經過定義函數,以實參的形式傳遞,在父組件捕獲的形式來獲取想要傳遞的參數,那麼在React中這個辦法是否也一樣適用呢?答案是確定的,依舊是經過父組件聲明函數,傳遞給子組件,子組件調用並傳入參數,在父組件捕獲便可。

export default class App extends Component {
    constructor(){
        super()
        this.state={
            myPatams:"test"
        }
    }
    getParams(params){
        console.log(params,this)
        this.setState({
            myPatams:params
        })
    }
    render() {
        //要想使用子組件也很簡單 用標籤的形式拿進來就行了
        return (
            <div> {this.state.myPatams} <Children params={"我從父組件傳過來"} getParams={this.getParams.bind(this)}></Children> {/* 這裏咱們把函數傳遞下去,必定要bind this 不然在咱們在子組件中使用bind來調用的時候,this的指向會跑到子組件中 咱們拿到的參數意義就不大了 固然箭頭函數也是徹底沒問題的 */} </div>
        )
    }
  
}

//下面咱們再寫一個class 而且繼承 Component 這就是一個組件了

class Children extends Component{
    constructor(){
        super()
        this.state={
        
        }
    }
    render(){

        return(
            <div> <h1>我是子組件</h1> <button onClick={this.props.getParams.bind(this,"我是子傳過來的參數")}>子傳父參</button> {/* 咱們在這裏調用父組件傳遞過來的方法,而且傳入參數 */} </div>
        )
    }
}

Children.defaultProps = {
    params: '我是默認的東西'
};


複製代碼

非父非子傳參(events 方法) 這種非關係型組件傳參通常使用redux來傳參,這裏咱們還有沒學習到,咱們藉助node的EventEmitter也能夠輕鬆實現

import React,{Component} from 'react'
// 首先咱們建立一個監聽器
import EventEmitter from 'events'; //事件監控對象
let emitter = new EventEmitter; //建立一個事件監控者 普通級別的監聽
emitter.setMaxListeners(100000); //設置監控管理器的最大監聽數量
export default class App extends Component {
    constructor(){
        super()
        this.state={
            myPatams:"test"
        }
    }
    getParams(params){
        console.log(params,this)
        this.setState({
            myPatams:params
        })
    }
    render() {
        //要想使用子組件也很簡單 用標籤的形式拿進來就行了
        return (
            <div> {this.state.myPatams} <Children params={"我從父組件傳過來"} getParams={this.getParams.bind(this)}></Children> {/* 這裏咱們把函數傳遞下去,必定要bind this 不然在咱們在子組件中使用bind來調用的時候,this的指向會跑到子組件中 咱們拿到的參數意義就不大了 固然箭頭函數也是徹底沒問題的 */} <ChildrenTwo /> </div>
        )
    }
  
}

//下面咱們再寫一個class 而且繼承 Component 這就是一個組件了

class Children extends Component{
    constructor(){
        super()
        this.state={
            emit:""
        }
    }
    componentWillMount(){
        emitter.on('childrenEmit',(param)=>{  //咱們在這裏設置監聽
            console.log(param)
            this.setState({
                emit:param
            })
        })
    }
    render(){

        return(
            <div> <h1>{this.state.emit}</h1> <button onClick={this.props.getParams.bind(this,"我是子傳過來的參數")}>子傳父參</button> {/* 咱們在這裏調用父組件傳遞過來的方法,而且傳入參數 */} </div>
        )
    }
}

class ChildrenTwo extends Component{
    constructor(){
        super()
        this.state={
        
        }
    }
    gaveParams(param){
        emitter.emit('childrenEmit',param)  //從第二個子組件觸發而且傳遞參數
    }
    render(){

        return(
            <div> <h1>我是子組件</h1> <button onClick={this.gaveParams.bind(this,"我是ChildrenTwo傳過來的參數")}>非父非子傳參</button> </div>
        )
    }
}



複製代碼

組件抽離

寫了這麼多,相信你們差很少會寫本身的組件而且在組件中傳遞參數了,這裏還有一個問題,你們是否是發現個人全部組件都寫在了一個JS內部,這樣若是是一個大項目,咱們的這個JS就會變地很是臃腫,這時候咱們就要抽離這個組件。實際上很是簡單,用到的就是咱們ES6的 export 導出 便可 若是隻有一個組件 那麼 還能夠像咱們書寫App這個基礎組件同樣 使用 export default 默認導出

這裏我給你們抽離一下

// App.js
import React,{Component} from 'react'
import {Children} from './components/Children.js'  // 由於咱們的Children中使用的是 export 來暴露

//import Children from './components/Children.js' // 若是使用的是 export default 則應該這樣寫

export default class App extends Component {
    constructor(){
        super()
        this.state={
            myPatams:"test"
        }
    }
    getParams(params){
        console.log(params,this)
        this.setState({
            myPatams:params
        })
    }
    render() {
        //要想使用子組件也很簡單 用標籤的形式拿進來就行了
        return (
            <div> {this.state.myPatams} <Children params={"我從父組件傳過來"} getParams={this.getParams.bind(this)}></Children> {/* 這裏咱們把函數傳遞下去,必定要bind this 不然在咱們在子組件中使用bind來調用的時候,this的指向會跑到子組件中 咱們拿到的參數意義就不大了 固然箭頭函數也是徹底沒問題的 */} </div>
        )
    }
  
}
複製代碼
// children.js
import React,{Component} from 'react'

// 當咱們抽離出來之後 必需要再次引入 react的必要組件

export class Children extends Component{  //咱們這裏使用的是export來暴露 若是隻有一個組件 也可使用 export default 來暴露
    constructor(){
        super()
        this.state={
        
        }
    }
    render(){

        return(
            <div> <h1>我是子組件</h1> <button onClick={this.props.getParams.bind(this,"我是子傳過來的參數")}>子傳父參</button> {/* 咱們在這裏調用父組件傳遞過來的方法,而且傳入參數 */} </div>
        )
    }
}

Children.defaultProps = {
    params: '我是默認的東西'
};


複製代碼

大功告成了 代碼是否是清晰多了??

總結

這一期內容很少 主要是介紹組件的生命週期 使用方法 以及如何傳參,這些內容可全都是乾貨,工做中會常常常用到,但願你們能本身寫小demo來熟悉一下寫法,下一期將會帶你們學習React-Router 以及context和高階組件的建立,爲咱們學習Redux打下基礎

視頻製做中

相關文章
相關標籤/搜索