博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React反模式 —— 如何不使用JSX地动态显示组件
阅读量:5236 次
发布时间:2019-06-14

本文共 3665 字,大约阅读时间需要 12 分钟。

欢迎指导与讨论 : )

  前言

    文章的最后能写出以 Modal.open( ) 这种调用形式,动态显示React对话框组件的写法(类似于ant design),同时涉及数据交互(数据能异步地返回给调用者)。笔者将和大家一起探讨这种写法的大概思路、难点,细节问题欢迎指出和补充。 O(∩_∩)O

    本文Demo地址:https://github.com/Penggggg/react-model-demo

    关于Angular-1的动态组件的思路的Demo地址:https://github.com/Penggggg/angular-component-practices

    欢迎 Star ~

 

  最终效果图

// 调用代码import Model from './Model;    onClick = ( ) => {        Model.show({ msg: 'Are you a Man?', title: 'Hello!' })            .then(( value: string ) => {               // 点击Yes按钮后返回的数据                console.log(` value: ${value}`);            })            .catch( e => {              // 点击No按钮后返回的数据                 console.log(`e`);            })    }

 

  探讨1:如何不使用JSX也能显示React.Component实例

    主要思路是:实例化一个组件 --> 渲染成Dom --> 插入到body元素内。

    其中实例化与渲染成Dom可以使用ReactDomrender函数去完成:  let _model = ReactDom.render(<Model />, div); 其中 div 是这个组件实例的一个容器(container dom),我们可以这样生产这个容器dom:  let div = document.createElement('div'); 。最后只需要把渲染结果插入到body元素中: document.querySelector('body').appendChild( div );

// 组合起来就是 let div = document.createElement('div');let _model = ReactDom.render(
, div);let dom = document.querySelector('body').appendChild(div);

 

  探讨2:交互数据如何异步地返回给调用者

    由于Modal组件涉及到数据交互(我们需要知道用户点击了Yes还是No),因此我们还需要将完成点击之后的数据异步地返回给调用者。同时,由于Modal的调用模式是 Modal.show( ) ,因此我决定在 Modal.show( ) 执行时,返回一个Promise给调用者

// 因此,整个调用模式看起来会像:Model.show( )    .then(( value: string ) => {           // 点击Yes后的代码(可以拿到数据value)     })     .catch( e => {           // 点击No后的代码     })

    现在就剩下如何实现上面所说的了。

    首先由于Modal是一个Class(类),因此我们需要把show函数作为Model 类的静态方法:

// Modal.jsexport default class Model extends React.PureComponent{          static show( ) { // .... }  }

    其次,我们需要返回一个实例的Promise,并且能够在Modal类方法地任意地方能够调用这个Promise实例  resolve( ) 和  reject( ) 方法从返回数据给调用者,因此我们把代码改动为

// Modal.jsexport default class Model extends React.PureComponent{     _resolve;     _reject;     _promise = new Promise (( resolve, reject) => {        this._resolve = resolve;        this._reject = reject;    })     static show( ) { // .... }  }

    然后,为静态方法show( )函数加上一些逻辑:

// 静态方法show( ) static show( ) {        // 弹出成功!        let div = document.createElement('div');        let _model: any = ReactDom.render(
, div); let dom = document.querySelector('body').appendChild(div); // 还记得我们需要return 一个promise吗 return _model._promise;}

    注意,这里的重点是:ReactDom.render( )会返回一个组件实例的js引用,而body.append( )会返回这个组件实例的dom引用,这两点很重要。

 

  探讨3:点击按钮执行返回数据

    有了上面的代码,这部分的实现就容易多了。首先先在Model的render函数里面把对话框的基本结构写出来(JSX),然后是为Yes/No按钮<button >分别添加一个react的点击事件

// Modal render函数    render( ) {
let { title, msg } = this.props; return(

{title}

{ msg }
) }
// Yes/No按钮点击后的处理函数     onNo = ( ) => {// 点击No后,调用者收到'i choice no'数据        this._reject('i choice no');  }  onYes = ( ) => {// 点击Yes后,调用者收到'i choice yes'数据        this._resolve('i choice yes');    }

 

  探讨4:如何销毁无用的组件实例及其内存

    点击完成后,Modal用处就不大了。那我们要怎么销毁这个组件实例,以在文档里面移除domj结果,并回收这个实例的内存呢。答案是ReactDomunmountComponentAtNode函数

    因此,我们需要在 onYes( ) 和 onNo( ) 里面继续添加相应的逻辑:

// 以onYes( ) 为例onYes = ( ) => {    this._resolve('i choice yes');    // 销毁    ReactDom.unmountComponentAtNode( this._container );    this._dom.remove( );       }// 其中:this._container 来自于这部分代码// static show( )let div = document.createElement('div');let _model = ReactDom.render(

 

 

  完,欢迎补充和指出问题。完整代码请参考上面地址 O(∩_∩)O

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/BestMePeng/p/React_modal.html

你可能感兴趣的文章
安装cocoa pods时出现Operation not permitted - /usr/bin/xcodeproj的问题
查看>>
GIT笔记:将项目发布到码云
查看>>
JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别
查看>>
JavaScript 鸭子模型
查看>>
SQL Server 如何查询表定义的列和索引信息
查看>>
GCD 之线程死锁
查看>>
NoSQL数据库常见分类
查看>>
一题多解 之 Bat
查看>>
Java 内部类
查看>>
{面试题7: 使用两个队列实现一个栈}
查看>>
【练习】使用事务和锁定语句
查看>>
centos7升级firefox的flash插件
查看>>
Apache Common-IO 使用
查看>>
评价意见整合
查看>>
二、create-react-app自定义配置
查看>>
Android PullToRefreshExpandableListView的点击事件
查看>>
系统的横向结构(AOP)
查看>>
linux常用命令
查看>>
NHibernate.3.0.Cookbook第四章第6节的翻译
查看>>
使用shared memory 计算矩阵乘法 (其实并没有加速多少)
查看>>