React實(shí)現(xiàn)動(dòng)態(tài)調(diào)用的彈框組件
最近在用react開(kāi)發(fā)項(xiàng)目,遇到一個(gè)需求——開(kāi)發(fā)一個(gè)彈框組件。在react中創(chuàng)建一個(gè)組件是很簡(jiǎn)單的,只需要使用class創(chuàng)建并引入就可以了,但是要做到可以用js調(diào)用這個(gè)組件而不是寫(xiě)在jsx結(jié)構(gòu)里,那就需要用到ReactDOM.render這個(gè)方法了。
首先先來(lái)屢一下需求:
1、彈框里的可配置字段:標(biāo)題文字,提示文字,確認(rèn)和取消按鈕的顯示隱藏以及文字。
2、點(diǎn)擊確認(rèn)和取消按鈕后,可以觸發(fā)相應(yīng)的事件。
3、是否為短提示,短提示的時(shí)候,確認(rèn)和取消按鈕隱藏,并且2s后消失。
接下來(lái)用兩種方法創(chuàng)建一個(gè)彈框組件,并比較一下這兩種的差異。
下面先來(lái)實(shí)現(xiàn)一個(gè)普通的寫(xiě)在jsx結(jié)構(gòu)里的組件:
彈框組件:DialogAlert.js
import React, { Component } from 'react';
import './index.scss';
?
class DialogAlert extends Component {
? ? constructor(props){
? ? ? ? super(props);
? ? ? ? this.state = {
? ? ? ? ? ? alertStatus:false,
? ? ? ? ? ? alertTitle:'提示', //標(biāo)題
? ? ? ? ? ? alertTip:'網(wǎng)絡(luò)錯(cuò)誤', //提示
? ? ? ? ? ? cancelText:'取消',
? ? ? ? ? ? confirmText:'確認(rèn)',
?
? ? ? ? ? ? isShortTip:false, //是否為短提示,短提示的情況下不顯示'取消''確認(rèn)'(且2s后消失),且優(yōu)先級(jí)最高,其他配置無(wú)效
?
? ? ? ? ? ? isShowCancel:true, //是否顯示確認(rèn)按鈕
? ? ? ? ? ? isShowConfirm:true, //是否顯示確認(rèn)按鈕
?
? ? ? ? ? ? cancelCallbackFn:function(){}, //取消 回調(diào)函數(shù)
? ? ? ? ? ? confirmCallbackFn:function (){}//確認(rèn) 回調(diào)函數(shù)
? ? ? ? }
? ? }
?
? ? 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()
? ? }
? ? //確認(rèn)
? ? 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;這里的數(shù)據(jù)更新用到了componentWillReceiveProps這個(gè)生命周期,當(dāng)props發(fā)生變化時(shí)執(zhí)行,初始化render時(shí)不執(zhí)行,在這個(gè)回調(diào)函數(shù)里面,你可以根據(jù)屬性的變化,通過(guò)調(diào)用this.setState()來(lái)更新你的組件狀態(tài),舊的屬性還是可以通過(guò)this.props來(lái)獲取,這里調(diào)用更新?tīng)顟B(tài)是安全的,并不會(huì)觸發(fā)額外的render調(diào)用。
調(diào)用頁(yè)面index.js
在state中定義可配置字段的變量
import DialogAlert from '../../widget/DialogAlert/index';
?
//省略了組件的js
?
this.state = {
? ? dialogOpt:{
? ? ? ? alertStatus:false,
? ? ? ? alertTip:'我是自定義的內(nèi)容',
? ? ? ? cancelText:'取消2',
? ? ? ? confirmText:'確認(rèn)2',
? ? ? ? isShortTip:false,
? ? ? ? isShowCancel:true, //是否顯示確認(rèn)按鈕
? ? ? ? isShowConfirm:true, //是否顯示確認(rèn)按鈕
? ? ? ? cancelCallbackFn:function(){
? ? ? ? ? alert(0);
? ? ? ? }, //取消 回調(diào)函數(shù)
? ? ? ? confirmCallbackFn:function (){
? ? ? ? ? alert(1);
? ? ? ? }//確認(rèn) 回調(diào)函數(shù)
? ? ? },
? ? ? //其他數(shù)據(jù)
? ? };在jsx中埋好對(duì)應(yīng)的組件結(jié)構(gòu)
<div onClick={()=>(this.alertdialog())}>點(diǎn)擊觸發(fā)彈框</div>
<DialogAlert dialogOpt={this.state.dialogOpt}></DialogAlert>添加觸發(fā)事件
alertdialog(){
? ? let opts = {
? ? ? alertStatus:true
? ? }
? ? let _dialogOpt = Object.assign(this.state.dialogOpt,opts)
? ? this.setState({
? ? ? dialogOpt:_dialogOpt
? ? })
? }這樣就完成一個(gè)普通的彈框??偢杏X(jué)這樣寫(xiě)的一個(gè)組件彈框有點(diǎn)冗余,復(fù)用起來(lái)也比較麻煩——在state里配置所有自定義的變量,并改動(dòng)jsx結(jié)構(gòu),還需要注意寫(xiě)入jsx結(jié)構(gòu)時(shí)彈框的層級(jí)問(wèn)題。
接下來(lái)我們來(lái)實(shí)現(xiàn)一種可動(dòng)態(tài)調(diào)用的組件:
原理是創(chuàng)建一個(gè)div,并插入到body里面,用這個(gè)div當(dāng)容器,使用render渲染組件,通過(guò)改變組件的state來(lái)控制組件的顯示和隱藏。
彈框組件:DialogAlert.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
?
//調(diào)用方法
// DialogAlert.open({
? ? // alertTitle:'提示2',
? ? // alertTip:"頁(yè)面加載失敗,是否重新加載?",
? ? // cancelText:'取消',
? ? // confirmText:'重新加載',
? ? // isShortTip:true,
? ? // isShowCancel:true,
? ? // isShowConfirm:true,
? ? // cancelCallbackFn:function(){
? ? // ? console.log('取消了')
? ? // },
? ? // confirmCallbackFn:function (){
? ? // ? console.log("確認(rèn)了...");
? ? // }
// });
?
class DialogBox extends Component {
? ? constructor(props){
? ? ? ? super(props);
? ? ? ? this.state = {
? ? ? ? ? ? alertStatus: false, //是否顯示提示框
?
? ? ? ? ? ? alertTitle:'提示', //標(biāo)題
? ? ? ? ? ? alertTip:'網(wǎng)絡(luò)錯(cuò)誤', //提示
? ? ? ? ? ? cancelText:'取消',
? ? ? ? ? ? confirmText:'確認(rèn)',
?
? ? ? ? ? ? isShortTip:false, //是否為短提示,短提示的情況下不顯示'取消''確認(rèn)'(且2s后消失),且優(yōu)先級(jí)最高,其他配置無(wú)效
?
? ? ? ? ? ? isShowCancel:true, //是否顯示確認(rèn)按鈕
? ? ? ? ? ? isShowConfirm:true, //是否顯示確認(rèn)按鈕
?
? ? ? ? ? ? cancelCallbackFn:function(){}, //取消 回調(diào)函數(shù)
? ? ? ? ? ? confirmCallbackFn:function (){}//確認(rèn) 回調(diào)函數(shù)
? ? ? ? }
? ? }
?
? ? //打開(kāi)提示框
? ? 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()
? ? }
? ? //確認(rèn)
? ? 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); //返回實(shí)例
?
export default DialogAlert;調(diào)用頁(yè)面index.js
import DialogAlert from '../../widget/DialogAlert/index';
? ?
//省略了組件的js
?
DialogAlert.open({
? ? alertTip:"加載失敗,是否重新加載?",
? ? confirmText:'重新加載',
? ? cancelCallbackFn:()=>{
? ? ? ? window.history.back();
? ? },
? ? confirmCallbackFn:()=>{
? ? ? ? //todo...
? ? }
})這里用到了ReactDOM.render,官方文檔說(shuō)這個(gè)方法目前會(huì)返回了對(duì)根組件實(shí)例的引用,所以我們可以調(diào)用到里面的open方法。但是官方文檔中目前應(yīng)該避免使用返回的引用,因?yàn)樗菤v史遺留下來(lái)的內(nèi)容。為了以后的react更新迭代的兼容,我們可以省去動(dòng)態(tài)插入組件的過(guò)程,改為寫(xiě)在jsx中,并設(shè)置ref,使用this.refs.xxx獲取當(dāng)前組件的實(shí)例,以便調(diào)用實(shí)例方法。
只需引入之后,直接調(diào)用就可以了。這樣寫(xiě)的好處是解決了彈框的層級(jí)問(wèn)題,也不用去改動(dòng)jsx結(jié)構(gòu),其他頁(yè)面復(fù)用起來(lái)更加方便快捷。
這兩種方法在組件的定義上并沒(méi)有很大的不同,只是在更新?tīng)顟B(tài)的時(shí)候有差異。第一種方法是在componentWillReceiveProps這個(gè)生命周期中監(jiān)聽(tīng)父組件的值的變化再更新到state上,第二中方法是直接調(diào)用實(shí)例的open方法通過(guò)獲取參數(shù)將值更新到state上。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
React在Dva項(xiàng)目中創(chuàng)建并引用頁(yè)面局部組件的方式
這篇文章主要介紹了React在Dva項(xiàng)目中創(chuàng)建并引用頁(yè)面局部組件的方式,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
React中Suspense及l(fā)azy()懶加載及代碼分割原理和使用方式
這篇文章主要介紹了React中Suspense及l(fā)azy()懶加載及代碼分割原理和使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
React創(chuàng)建組件的三種方式及其區(qū)別
本文主要介紹了React創(chuàng)建組件的三種方式及其區(qū)別,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
ReactJS實(shí)現(xiàn)表單的單選多選和反選的示例
本篇文章主要介紹了ReactJS實(shí)現(xiàn)表單的單選多選和反選的示例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-10-10
React通過(guò)redux-persist持久化數(shù)據(jù)存儲(chǔ)的方法示例
這篇文章主要介紹了React通過(guò)redux-persist持久化數(shù)據(jù)存儲(chǔ)的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
react native 原生模塊橋接的簡(jiǎn)單說(shuō)明小結(jié)
這篇文章主要介紹了react native 原生模塊橋接的簡(jiǎn)單說(shuō)明小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02

