日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React實現動態調用的彈框組件_React

作者:qq_35757537 ? 更新時間: 2022-10-21 編程語言

最近在用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上。

原文鏈接:https://blog.csdn.net/qq_35757537/article/details/90322144

欄目分類
最近更新