網站首頁 編程語言 正文
最近在用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
相關推薦
- 2022-11-21 Pandas數據分析之groupby函數用法實例詳解_python
- 2022-06-22 android選項卡TabHost功能用法詳解_Android
- 2021-12-24 OpenCV?reshape函數實現矩陣元素序列化_C 語言
- 2022-03-28 Python?NumPy實用函數筆記之allclose_python
- 2022-07-27 關于pytest結合csv模塊實現csv格式的數據驅動問題_python
- 2022-06-07 nlp計數法應用于PTB數據集示例詳解_python
- 2022-04-11 基于python實現Pycharm斷點調試_python
- 2022-12-15 python將二維數組升為一維數組或二維降為一維方法實例_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支