Material-UI-React-Snackbars-提示

React+Electron桌面應(yīng)用開(kāi)發(fā)文章索引

這篇文章繼續(xù)之前的文章坷虑。比起彈窗,底部彈出的小提示更加頻繁滔灶,這次我們介紹如何創(chuàng)建小提示Snackbar瘦癌。

MaterialUI官方給出了Snackbar實(shí)現(xiàn)案例,也很繁瑣乌叶,小提示本質(zhì)上也是全局性的改化,但與彈窗略有區(qū)別的是,小提示可以同時(shí)出現(xiàn)多個(gè)枉昏。

這次我們還是想辦法把它統(tǒng)一化陈肛。


思路分析

snackbar的功能特征:

  • 和彈窗一樣,包含內(nèi)容區(qū)(純文字兄裂,或文字+按鈕)和一個(gè)關(guān)閉按鈕

  • snackbar并不打斷用戶操作句旱,大多時(shí)候會(huì)幾秒后自動(dòng)消失

  • 所以可能有多個(gè)snackbar同時(shí)出現(xiàn)

  • snackbar看上去也是全局性的功能阳藻,但實(shí)際應(yīng)該是多個(gè)元素

  • 在任意頁(yè)面都可以創(chuàng)建snackbar

  • snackbar都應(yīng)該放在App的某個(gè)容器里面統(tǒng)一接管,添加或移除

  • 我們需要一個(gè)快速創(chuàng)建snackbar的全局功能global.$addSnackbar(state)


編寫(xiě)代碼

創(chuàng)建Utitlies/MySnackbar.js。

實(shí)現(xiàn)思路是:

  • 創(chuàng)建一個(gè)snackbars局部變量谈撒,用來(lái)存放所有實(shí)例腥泥,這樣就可以跨越執(zhí)行實(shí)例.setState({open:false})方法關(guān)閉snackbar。(參考xset的實(shí)現(xiàn)思路)

  • 實(shí)現(xiàn)全局化的global.$closeMySnackBar通過(guò)id關(guān)閉特定snackbar方法

  • 創(chuàng)建一個(gè)MySnackbar類啃匿,constructor構(gòu)建函數(shù)里面把每個(gè)實(shí)例通過(guò)id添加到snackbars蛔外,以后就能使用snackbars[id]來(lái)獲取

  • MySnackbar類中render()通過(guò)style實(shí)現(xiàn)了snackbar的堆疊效果,通過(guò)覆蓋onClose關(guān)閉方法實(shí)現(xiàn)autoHideDuration倒計(jì)時(shí)結(jié)束自動(dòng)關(guān)閉

  • MySnackbars類是所有snackbar界面dom的容器溯乒,全局化了global.$addMySnackbar方法用來(lái)添加新的snackbar

  • id這個(gè)參數(shù)專門用來(lái)配合snackbars變量管理和獲取創(chuàng)建的MySnackbar實(shí)例

/*
被加載時(shí)候componentDidMount添加全局方法:
$addSnackbar(state,id)夹厌,state格式請(qǐng)參照官方API說(shuō)明,必須通過(guò)id才能自定義關(guān)閉snackbar的按鈕
$closeMySnackBar(id),關(guān)閉特定的snackbar
*/
import React from 'react'
import h from 'react-hyperscript'
import deepmerge from 'deepmerge'

import Button from 'material-ui/Button'
import Snackbar from 'material-ui/Snackbar'

let snackbars = {} //全部snackbar實(shí)例列表裆悄,關(guān)閉snackbar時(shí)候使用

//輸出關(guān)閉特定snackbar的全局方法
global.$closeMySnackBar = (id) => {
    if (snackbars[id]) {
        snackbars[id].setState({
            open: false
        })
    }
}

/*
自動(dòng)接收snackbar管理的類
能夠自動(dòng)計(jì)時(shí)關(guān)閉
*/
class MySnackbar extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            open: true
        }
    }

    componentDidMount() {
        if (this.props.id) {
            snackbars[this.props.id] = this
        }
    }

    render() {
        let props = deepmerge(this.props, {
            open: this.state.open,
            style: {
                display: 'block',
                position: 'relative',
                height: 56,
            },
            onClose: (event, reason) => {
                this.props.onClose && this.props.onClose()
                if (reason !== 'clickaway') this.setState({
                    open: false
                })
            },
        })
        return h(Snackbar, props)
    }
}

//App中所有snackbar的容器管理
class MySnackbars extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            list: []
        }
    }

    add(state, id) {
        console.log('xx', id)
        let newOne = h(MySnackbar, deepmerge(state, {
            open: true,
            id: id //關(guān)閉snackbar時(shí)候使用
        }))
        this.state.list.push(newOne)
        this.setState({
            list: this.state.list
        })
    }

    componentDidMount() {
        let that = this;
        global.$addMySnackbar = (state, id) => {
            that.add(state, id)
        }
    }

    render() {
        //嵌套兩層div把所有snackbar固定在底部中間
        return h('div', {
            style: {
                bottom: 8,
                position: 'fixed',
                textAlign: 'center',
                width: '100%'
            }
        }, [
            h('div', {
                style: {
                    display: 'inline-block',
                }
            }, this.state.list)
        ])
    }
}

export default MySnackbars

使用MySnackbars

首先我們還是在App.js中引入import MySnackbar from '../Utilities/MySnackbars',并在render()中創(chuàng)建放置snackbars的容器

    render() {
        let that = this
        const css = this.props.classes

        return h(MuiThemeProvider, {
            theme: Theme,
        }, h(Grid, {
            container: false,
            className: css.app,
        }, [
            h(Pages[this.state.currentPageName]),
            h(MyDialog),
            h(MySnackbar),
        ]))
    }

然后我們就可以在其他頁(yè)面中使用了矛纹,比如:

            h(Button, {
                onClick: () => {
                    let id = Math.random()
                    global.$addMySnackbar({
                        anchorOrigin: {
                            vertical: 'bottom',
                            horizontal: 'center',
                        },
                        autoHideDuration: 3000,
                        onClose: () => {
                            console.log('Home Page said:', that.state.title)
                        },
                        message: 'Hello from MySnackbar!',
                        action: [
                            h(Button, {
                                key: 'any',//必須要有這個(gè),值任意
                                color: 'secondary',
                                onClick: () => {
                                    global.$closeMySnackBar(id)
                                    console.log('Home Page said:', that.state.title)
                                }
                            }, '關(guān)閉')
                        ],
                    }, id)
                }
            }, 'add snackbar'),

這生成一個(gè)按鈕

點(diǎn)擊它彈出

多次點(diǎn)擊彈出多個(gè)


點(diǎn)擊紫色按鈕可以關(guān)閉某個(gè)snackbar光稼,或者超過(guò)3秒鐘自動(dòng)消失


致力于讓一切變得簡(jiǎn)單

如果您發(fā)現(xiàn)文章錯(cuò)誤或南,請(qǐng)不吝留言指正;
如果您覺(jué)得有用艾君,請(qǐng)點(diǎn)喜歡采够;
如果您覺(jué)得很有用,歡迎轉(zhuǎn)載~


END

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冰垄,一起剝皮案震驚了整個(gè)濱河市蹬癌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌播演,老刑警劉巖冀瓦,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伴奥,死亡現(xiàn)場(chǎng)離奇詭異写烤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)拾徙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門洲炊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人尼啡,你說(shuō)我怎么就攤上這事暂衡。” “怎么了崖瞭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵狂巢,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我书聚,道長(zhǎng)唧领,這世上最難降的妖魔是什么藻雌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮斩个,結(jié)果婚禮上胯杭,老公的妹妹穿的比我還像新娘。我一直安慰自己受啥,他們只是感情好做个,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著滚局,像睡著了一般居暖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上核畴,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天膝但,我揣著相機(jī)與錄音,去河邊找鬼谤草。 笑死跟束,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的丑孩。 我是一名探鬼主播冀宴,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼温学!你這毒婦竟也來(lái)了略贮?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤仗岖,失蹤者是張志新(化名)和其女友劉穎逃延,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體轧拄,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡揽祥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了檩电。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拄丰。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俐末,靈堂內(nèi)的尸體忽然破棺而出料按,到底是詐尸還是另有隱情,我是刑警寧澤卓箫,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布载矿,位于F島的核電站,受9級(jí)特大地震影響烹卒,放射性物質(zhì)發(fā)生泄漏闷盔。R本人自食惡果不足惜魂挂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望馁筐。 院中可真熱鬧涂召,春花似錦、人聲如沸敏沉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)盟迟。三九已至秋泳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間攒菠,已是汗流浹背迫皱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辖众,地道東北人卓起。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凹炸,于是被迫代替她去往敵國(guó)和親戏阅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容