国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一個(gè)播放器引發(fā)的思考——談?wù)凴eact跨組件通信

Dean / 3097人閱讀

摘要:如果某個(gè)組件訂閱該事件太晚,那發(fā)布者之前所發(fā)布的該類事件,它都接收不到,而方案一和二的優(yōu)點(diǎn)則在于,無(wú)論如何,組件都能拿到該的最終狀態(tài)值有存在內(nèi)存泄漏的風(fēng)險(xiǎn)。

原文地址 - 歡迎關(guān)注我的博客

在我們r(jià)eact項(xiàng)目日常開發(fā)中,往往會(huì)遇到這樣一個(gè)問(wèn)題:如何去實(shí)現(xiàn)跨組件通信?

為了更好的理解此問(wèn)題,接下來(lái)我們通過(guò)一個(gè)簡(jiǎn)單的栗子說(shuō)明。

實(shí)現(xiàn)一個(gè)視頻播放器

假設(shè)有一個(gè)這樣的需求,需要我們?nèi)?shí)現(xiàn)一個(gè)簡(jiǎn)易的視頻播放器,基于對(duì)播放器的理解,我們可以把這個(gè)視頻播放器大致分為如下幾個(gè)部分:

視頻窗口組件Screen

底部播放控件BottomCtrl

對(duì)于視頻窗口組件,它包含一個(gè)播放/暫停按鈕CenterPlayBtn;而底部播放控件又是由以下幾種組件組合而成:

播放/暫停按鈕BottomPlayBtn

進(jìn)度控制條ProgressCtrl

音量按鈕Volume

于是乎它的構(gòu)成應(yīng)該如下圖所示:

同樣的,我們的組件組織方式應(yīng)該也長(zhǎng)這樣:(這里簡(jiǎn)化了代碼實(shí)現(xiàn))

class MyVideo {
  render() {
    return (
      
) } } // 底部視頻控件 class BottomCtrl { render() { return (
) } } // 視頻窗口組件 class Screen { render() { return (
) } }

對(duì)于視頻播放器而言,有一個(gè)很常見的交互,即當(dāng)我們點(diǎn)擊屏幕中心的播放按鈕CenterPlayBtn時(shí),不僅需要改變自身的狀態(tài)(隱藏起來(lái)),而且還要更新底部播放按鈕BottomPlayBtn的樣式

由于中心播放按鈕與底部控件按鈕分別屬于ScreenBottomCtrl組件的部分,因此這就是一個(gè)很常見的跨組件通信問(wèn)題:如何將CenterPlayBtn的狀態(tài)同步到BottomPlayBtn?

方案一:祖先組件的狀態(tài)管理

一個(gè)非常常用的方式,就是讓祖先組件通過(guò)狀態(tài)管理的方式把信息同步到其他子組件中:

class MyVideo {
    constructor(props) {
        super(props);
        this.state = {
            isPlay: false,
        }
    }
    
    updatePlayState = isPlay => {
        this.setState({ isPlay });
    }
    
    render() {
        const { isPlay } = this.state;
        return (
            
) } }

我們通過(guò)在祖先組件的state定義相應(yīng)的狀態(tài),并把修改state的方法傳遞給了子組件,那么當(dāng)一個(gè)子組件通過(guò)調(diào)用updatePlayState后,它所設(shè)置的新狀態(tài)亦可通過(guò)react本身的state更新機(jī)制傳遞給其他的子組件,實(shí)現(xiàn)跨組件通信。

這種方案雖然簡(jiǎn)單,但在一些復(fù)雜的場(chǎng)景下卻顯得不夠友好:

狀態(tài)和方法需要通過(guò)層層props傳遞到相應(yīng)的子組件,一旦組件嵌套過(guò)深,不好編寫與維護(hù),且對(duì)于中間傳遞的組件而言,增加了不必要的邏輯;

管理狀態(tài)的祖先組件將變得更加臃腫。試想一下,假設(shè)我們?yōu)榱藢?shí)現(xiàn)兩個(gè)嵌套很深的子組件的通信,卻需要在祖先組件上去額外添加狀態(tài)和方法,這增加了祖先組件的維護(hù)成本。

方案二:redux提供的跨組件通信能力

熟悉redux的童鞋都知道,redux提供的訂閱發(fā)布機(jī)制,可以讓我們實(shí)現(xiàn)任何兩個(gè)組件的通信:首先我們需要在state上去添加一個(gè)key,在兩個(gè)需要通信的組件上通過(guò)connect的封裝,即可訂閱key值的改變。

// CenterPlayBtn
class CenterPlayBtn {
    play() {
        this.props.updatePlayStatus();
    }
}

const mapDispatchToProps = dispatch => {
  return {
    updatePlayStatus: isPlay => {
      dispatch(updatePlayStatus(isPlay))
    }
  }
}

export default connect(null, mapDispatchToProps)(BottomPlayBtn)
class BottomPlayBtn {
    componentWillReceiveProps(nextProps) {
        if (this.props.isPlay !== nextProps.isPlay) {
            // do something
        }
    }
}

const mapStateToProps = state => ({
    isPlay: state.isPlay
})

export default connect(mapStateToProps, null)(BottomPlayBtn)

使用redux的方式去實(shí)現(xiàn)跨組件通信是一種很常見的方式,在項(xiàng)目開發(fā)中也經(jīng)常用到。那問(wèn)題又來(lái)了,由于使用這種方案的前提是必須得在項(xiàng)目中加入redux,如果我的項(xiàng)目本來(lái)就比較簡(jiǎn)單,不需要使用到redux,難道為了實(shí)現(xiàn)兩個(gè)組件簡(jiǎn)單的通信而要去做一系列redux的配置工作嗎?這顯然把簡(jiǎn)單的問(wèn)題又復(fù)雜化了。

方案三:EventEmitter

EventEmitter也可以實(shí)現(xiàn)跨組件通信,當(dāng)然這種基于事件訂閱的設(shè)計(jì)模式本身也與react關(guān)系不大,但我們的項(xiàng)目很小的時(shí)候,使用EventEmitter也不失為一種簡(jiǎn)單且高效的方式:

class CenterPlayBtn {

    constructor(props) {
        super(props);
        event.on("pause", () => {
            // do something
        })
    }

    play() {
        event.emit("play");
    }
}

class BottomPlayBtn {

    constructor(props) {
        super(props);
        event.on("play", () => {
            // do something
        })
    }

    pause() {
        event.emit("pause");
    }
}

當(dāng)然這種方案也是有缺陷的:

組織方式過(guò)于離散。發(fā)送者emit與接收者on分散在各個(gè)組件里,如果不細(xì)看每個(gè)組件的代碼,我們難以從整體去觀察、跟蹤、管理這些事件;

有可能出現(xiàn)錯(cuò)過(guò)某個(gè)事件的情況。如果某個(gè)組件訂閱該事件太晚,那發(fā)布者之前所發(fā)布的該類事件,它都接收不到,而方案一和二的優(yōu)點(diǎn)則在于,無(wú)論如何,組件都能拿到該key的最終狀態(tài)值;

有存在內(nèi)存泄漏的風(fēng)險(xiǎn)。如果組件銷毀了而不及時(shí)取消訂閱,那就有內(nèi)存泄漏的風(fēng)險(xiǎn);

方案四:利用react原生的context實(shí)現(xiàn)跨組件通信

原生react提供了context,它的原文描述是這樣的:

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

簡(jiǎn)單來(lái)說(shuō)就是react提供了一種方式,讓你可以跨多層嵌套組件去訪問(wèn)數(shù)據(jù),而不需要手動(dòng)的將props一個(gè)一個(gè)地傳遞下去。通過(guò)這種方式我們也可以實(shí)現(xiàn)跨組件通信方式,這個(gè)方案和方案一很相似,但區(qū)別在于我們無(wú)需手動(dòng)將props傳遞給經(jīng)歷的每一個(gè)中間層組件。更為具體的用法可以直接參考官網(wǎng)示例,下面只是拋磚引玉,給出個(gè)簡(jiǎn)單示例:

首先我們定義一個(gè)player-context.js文件

import { createContext } from "react";
const PlayerContext = createContext();
export default PlayerContext;

然后在MyVideo組件中使用PlayerContext.Provider:

import PlayerContext from "./player-context";

class MyVideo {
    constructor(props) {
        super(props);
        this.state = {
            isPlay: false,
            updatePlayState: this.updatePlayState,
        }
    }
    
    updatePlayState = isPlay => {
        this.setState({ isPlay });
    }
    
    render() {
        return (
            
                
                
            
        )
    }
}

接著在需要消費(fèi)數(shù)據(jù)的地方CenterPlayBtnBottomPlayBtn中使用到它,這里只給出CenterPlayBtn的示例:

import PlayerContext from "./player-context";

class CenterPlayBtn {

    constructor(props) {
        super(props);
    }

    play() {
        this.props.updatePlayStatus(!this.props.isPlay);
    }
    
    componentWillReceiveProps(nextProps) {
        if (this.props.isPlay !== nextProps.isPlay) {
            // do something...
        }
    }
}

export default props => (
    {
        ({isPlay, updatePlayStatus}) => 
    } 
)

其實(shí)個(gè)人認(rèn)為這種方案是方案一的“增強(qiáng)版”:

首先它像方案一一樣,對(duì)數(shù)據(jù)作了集中控制管理,即把提供數(shù)據(jù)內(nèi)容和修改數(shù)據(jù)的能力集中到了上層組件身上,使得上層組件成為唯一的Provider,供下層各處的消費(fèi)者Consumer使用;

其次它無(wú)須像方案一一樣繁瑣地將props手動(dòng)向下傳遞;

總得來(lái)說(shuō),如果你的項(xiàng)目沒有使用到redux的話,使用context是個(gè)不錯(cuò)的選擇。

總結(jié)

上面列舉的方案各有優(yōu)劣,我們很難去判定哪種方案是最好的,而真正重要的,是要學(xué)會(huì)分析哪個(gè)場(chǎng)景下使用哪種方案更佳。

btw,其實(shí)跨組件通信的方式多種多樣,遠(yuǎn)不止這些,本人才疏學(xué)淺,這里只能列舉出一些自己常用的解決方案,希望此文能拋磚引玉,引出更棒的方案和見解:)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/109636.html

相關(guān)文章

  • 一個(gè)放器引發(fā)思考——談?wù)?/em>React組件通信

    摘要:如果某個(gè)組件訂閱該事件太晚,那發(fā)布者之前所發(fā)布的該類事件,它都接收不到,而方案一和二的優(yōu)點(diǎn)則在于,無(wú)論如何,組件都能拿到該的最終狀態(tài)值有存在內(nèi)存泄漏的風(fēng)險(xiǎn)。 原文地址 - 歡迎關(guān)注我的博客 在我們r(jià)eact項(xiàng)目日常開發(fā)中,往往會(huì)遇到這樣一個(gè)問(wèn)題:如何去實(shí)現(xiàn)跨組件通信? 為了更好的理解此問(wèn)題,接下來(lái)我們通過(guò)一個(gè)簡(jiǎn)單的栗子說(shuō)明。 實(shí)現(xiàn)一個(gè)視頻播放器 假設(shè)有一個(gè)這樣的需求,需要我們?nèi)?shí)現(xiàn)一個(gè)...

    zhongmeizhi 評(píng)論0 收藏0
  • 關(guān)于Vue2一些值得推薦文章 -- 五、六月份

    摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

    sutaking 評(píng)論0 收藏0
  • 關(guān)于Vue2一些值得推薦文章 -- 五、六月份

    摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...

    khs1994 評(píng)論0 收藏0
  • 前端面試題總結(jié)(js、html、小程序、React、ES6、Vue、算法、全棧熱門視頻資源)

    摘要:并總結(jié)經(jīng)典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快速搭建項(xiàng)目。 本文是關(guān)注微信小程序的開發(fā)和面試問(wèn)題,由基礎(chǔ)到困難循序漸進(jìn),適合面試和開發(fā)小程序。并總結(jié)vue React html css js 經(jīng)典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快...

    pumpkin9 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<