<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
最近在用react開發專案,遇到一個需求——開發一個彈框元件。在react中建立一個元件是很簡單的,只需要使用class建立並引入就可以了,但是要做到可以用js呼叫這個元件而不是寫在jsx結構裡,那就需要用到ReactDOM.render這個方法了。
首先先來屢一下需求:
1、彈框裡的可設定欄位:標題文字,提示文字,確認和取消按鈕的顯示隱藏以及文字。
2、點選確認和取消按鈕後,可以觸發相應的事件。
3、是否為短提示,短提示的時候,確認和取消按鈕隱藏,並且2s後消失。
接下來用兩種方法建立一個彈框元件,並比較一下這兩種的差異。
下面先來實現一個普通的寫在jsx結構裡的元件:
彈框元件:DialogAlert.js
import React, { Component } from 'react'; import './index.scss'; class DialogAlert extends Component { constructor(props){ super(props); this.state = { alertStatus:false, alertTitle:'提示', //標題 alertTip:'網路錯誤', //提示 cancelText:'取消', confirmText:'確認', isShortTip:false, //是否為短提示,短提示的情況下不顯示'取消''確認'(且2s後消失),且優先順序最高,其他設定無效 isShowCancel:true, //是否顯示確認按鈕 isShowConfirm:true, //是否顯示確認按鈕 cancelCallbackFn:function(){}, //取消 回撥函數 confirmCallbackFn:function (){}//確認 回撥函數 } } componentWillReceiveProps(nextProps) { let options = nextProps.dialogOpt || {}; //如果是短提示 if(options.isShortTip){ options.isShowCancel = false; options.isShowConfirm = false; setTimeout(()=>{ this.close() },2000) } this.setState({ ...options }) } //取消 cancel = () => { this.state.cancelCallbackFn(); this.close() } //確認 confirm = () => { this.state.confirmCallbackFn(); this.close() } close = () => { this.setState({ alertStatus:false }) } render(){ let opts = this.state; return ( <div className="dialog-wrap" style={opts.alertStatus ? {display:'block'}:{display:'none'}}> <div className="dialog-box"> <h6>{opts.alertTitle}</h6> <p>{opts.alertTip}</p> {!opts.isShowCancel && !opts.isShowConfirm ? null : ( <div> {opts.isShowCancel ? (<span onClick={ () => this.cancel() }>{opts.cancelText}</span>) : null} {opts.isShowConfirm ? (<span className="confirm" onClick={ () => this.confirm() }>{opts.confirmText}</span>) : null} </div> )} </div> </div> ) } } export default DialogAlert;
這裡的資料更新用到了componentWillReceiveProps這個生命週期,當props發生變化時執行,初始化render時不執行,在這個回撥函數裡面,你可以根據屬性的變化,通過呼叫this.setState()來更新你的元件狀態,舊的屬性還是可以通過this.props來獲取,這裡呼叫更新狀態是安全的,並不會觸發額外的render呼叫。
呼叫頁面index.js
在state中定義可設定欄位的變數
import DialogAlert from '../../widget/DialogAlert/index'; //省略了元件的js this.state = { dialogOpt:{ alertStatus:false, alertTip:'我是自定義的內容', cancelText:'取消2', confirmText:'確認2', isShortTip:false, isShowCancel:true, //是否顯示確認按鈕 isShowConfirm:true, //是否顯示確認按鈕 cancelCallbackFn:function(){ alert(0); }, //取消 回撥函數 confirmCallbackFn:function (){ alert(1); }//確認 回撥函數 }, //其他資料 };
在jsx中埋好對應的元件結構
<div onClick={()=>(this.alertdialog())}>點選觸發彈框</div> <DialogAlert dialogOpt={this.state.dialogOpt}></DialogAlert>
新增觸發事件
alertdialog(){ let opts = { alertStatus:true } let _dialogOpt = Object.assign(this.state.dialogOpt,opts) this.setState({ dialogOpt:_dialogOpt }) }
這樣就完成一個普通的彈框。總感覺這樣寫的一個元件彈框有點冗餘,複用起來也比較麻煩——在state裡設定所有自定義的變數,並改動jsx結構,還需要注意寫入jsx結構時彈框的層級問題。
接下來我們來實現一種可動態呼叫的元件:
原理是建立一個div,並插入到body裡面,用這個div當容器,使用render渲染元件,通過改變元件的state來控制元件的顯示和隱藏。
彈框元件:DialogAlert.js
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import './index.scss'; //呼叫方法 // DialogAlert.open({ // alertTitle:'提示2', // alertTip:"頁面載入失敗,是否重新載入?", // cancelText:'取消', // confirmText:'重新載入', // isShortTip:true, // isShowCancel:true, // isShowConfirm:true, // cancelCallbackFn:function(){ // console.log('取消了') // }, // confirmCallbackFn:function (){ // console.log("確認了..."); // } // }); class DialogBox extends Component { constructor(props){ super(props); this.state = { alertStatus: false, //是否顯示提示框 alertTitle:'提示', //標題 alertTip:'網路錯誤', //提示 cancelText:'取消', confirmText:'確認', isShortTip:false, //是否為短提示,短提示的情況下不顯示'取消''確認'(且2s後消失),且優先順序最高,其他設定無效 isShowCancel:true, //是否顯示確認按鈕 isShowConfirm:true, //是否顯示確認按鈕 cancelCallbackFn:function(){}, //取消 回撥函數 confirmCallbackFn:function (){}//確認 回撥函數 } } //開啟提示框 open = (options) => { options = options || {}; //如果是短提示 if(options.isShortTip){ options.isShowCancel = false; options.isShowConfirm = false; setTimeout(()=>{ this.close() },2000) } options.alertStatus = true; this.setState({ ...options }) } //取消 cancel = () => { this.state.cancelCallbackFn(); this.close() } //確認 confirm = () => { this.state.confirmCallbackFn(); this.close() } close = () => { this.setState({ alertStatus:false }) } render(){ let opts = this.state; return ( <div className="dialog-wrap" style={opts.alertStatus? {display:'block'}:{display:'none'}}> <div className="dialog-box"> <h6>{opts.alertTitle}</h6> <p>{opts.alertTip}</p> {!opts.isShowCancel && !opts.isShowConfirm ? null : ( <div> {opts.isShowCancel ? (<span onClick={ () => this.cancel() }>{opts.cancelText}</span>) : null} {opts.isShowConfirm ? (<span className="confirm" onClick={ () => this.confirm() }>{opts.confirmText}</span>) : null} </div> )} </div> </div> ) } } let div = document.createElement('div'); document.body.appendChild(div); let DialogAlert = ReactDOM.render(<DialogBox /> ,div); //返回範例 export default DialogAlert;
呼叫頁面index.js
import DialogAlert from '../../widget/DialogAlert/index'; //省略了元件的js DialogAlert.open({ alertTip:"載入失敗,是否重新載入?", confirmText:'重新載入', cancelCallbackFn:()=>{ window.history.back(); }, confirmCallbackFn:()=>{ //todo... } })
這裡用到了ReactDOM.render,官方檔案說這個方法目前會返回了對根元件範例的參照,所以我們可以呼叫到裡面的open方法。但是官方檔案中目前應該避免使用返回的參照,因為它是歷史遺留下來的內容。為了以後的react更新迭代的相容,我們可以省去動態插入元件的過程,改為寫在jsx中,並設定ref,使用this.refs.xxx獲取當前元件的範例,以便呼叫實體方法。
只需引入之後,直接呼叫就可以了。這樣寫的好處是解決了彈框的層級問題,也不用去改動jsx結構,其他頁面複用起來更加方便快捷。
這兩種方法在元件的定義上並沒有很大的不同,只是在更新狀態的時候有差異。第一種方法是在componentWillReceiveProps這個生命週期中監聽父元件的值的變化再更新到state上,第二中方法是直接呼叫範例的open方法通過獲取引數將值更新到state上。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45