建立无需build的react单页面应用SPA框架(2)
react-18.1.0,rc-easyui-1.2.9,babel-7.17.11
SPA还要处理的问题:
(一)tabs切换事件通知
tabs切换时,自己的框架需要处理组件的生命周期,要有active/deactive,让组件能知道何时创建或清除一些资源的使用,比如setInterval/clearInterval。
赋予active/deactive事件通知,在tabs元件的onTabSelect/onTabUnselect事件处理就行了。如何通知?分两种情况:
(1)类式组件,让它定义一个function foil_onStateChanged(state)函数来接收。
page.likeButton.jsxclass Com_LikeButton extends React.Component {constructor(props) {console.log('likebutton constructor');super(props);this.state = { liked: false };}foil_onStateChanged(state){console.log('likebutton foil_onStateChanged',state);}render() {console.log('likeButton render',this.props);if (this.state.liked) {console.log(acroML.browserEngine.LCID);return t('&File');}return (<button onClick={() => this.setState({ liked: true })}>{t('&Edit')}</button>);}
}
export default Com_LikeButton;
(2)函数式组件,通过props参数传递。
page.timer.jsxexport default function COM_timer(props){console.log('page timer function:',props.foil.state);let [time,setTime]=React.useState(0);function getNow(){return time;}//timerID不参与渲染,用useReflet timerID=React.useRef(null);console.log('timerID:',timerID.current);if (props.foil.state=='create' || props.foil.state=='active'){if (timerID.current==null){console.log('start timer')timerID.current=setInterval(function(){console.log('timer:',time);time++;setTime(time);},1000);}}else if (props.foil.state=='deactive'||props.foil.state=='destroy'){if (timerID.current!=null){console.log('clear timerID:',timerID.current);clearInterval(timerID.current);timerID.current=null;}}return(<div><span>{t('&File')}</span><span>{getNow()}</span></div>)
}
虽然类组件有componentDidMount/componentWillUnmount两个事件来判断组件创建和销毁,但是函数式组件没有。如果框架要统一事件,最好把create/destroy事件也加进去。create可以在异步组件的componentDidMount处理,destroy就不能在动态元件的componentWillUnmount处理了,甚至不能在tabs的onTabClose事件处理,来不及了,虽然类组件可以,但函数式组件不会触发渲染重调用。
com.bizCom.jsximport { Suspense,Component } from 'react';
class Com_bizCom extends React.Component {constructor(props) {console.log('Com_bizCom constructor');super(props);props.foil.onStateChanged=this.foil_onStateChanged.bind(this);this.state={foil:{state:'create'}}}shouldComponentUpdate(nextProps, nextState) {//console.log(nextProps);//文件相同时不要再渲染,LCID改变后必须重渲染//if (nextProps.file && (nextProps.file === this.props.file)) return false;return true;}foil_onStateChanged(state){console.log('bizCom foil_onStateChanged',state);console.log(this.com);if (this.com.ref){//React.Component类组件可以通过函数通知状态if (this.com.ref.current.foil_onStateChanged){this.com.ref.current.foil_onStateChanged(state);}}else{//函数式组件只能通过proprs传递状态,然后bizCOM重渲染if (this.state.foil.state!=state){this.state.foil.state=state;this.com.props.foil.state=state;this.setState(this.state);}}}componentDidMount(){if (this.com.ref){//只需要组件元件通知一下create状态,函数元件第一渲染已经把create带到props.foil.statethis.com.ref.current.foil_onStateChanged('create');}}componentWillUnmount(){let self=this;console.log('bizCom componentWillUnmount',this.com.ref);//不在这里处理子函数式组件的销毁通知,来不及了,子函数式组件不会调用渲染//在easyui tab关闭前处理}render() {let self=this;console.log('Com_bizCom render',this.props);let file=this.props.file;if (!file) return null;/*let Com=React.lazy(function(){import函数不能加载jsxreturn import(file);});return(<Suspense><Com></Com></Suspense>)*/let obj=window.require(file);//console.log(obj);if (obj.__esModule===true) obj= obj.default;// console.log(typeof obj);// console.log(obj.prototype);console.log(self.com);let ops=null;if (self.com){ops=self.com.props;}else{ops={foil:{state:'create'}};if (obj.prototype && obj.prototype.isReactComponent){//类组件才有ref,函数式组件不能有refops.ref=React.createRef();}}let com=React.createElement(obj,ops);self.com=com;return com;}
}
export default Com_bizCom;
要在tabs的panel关闭前处理,查找easyui tabs源码,找到handleTabClose函数,hook一下:
com.right.jsx
............componentDidMount(){let self=this;console.log('right componentDidMount');console.log(this.ref_tabs.current.handleTabClose);//hook handleTabClose这个函数,在关闭panel前通知到bizCom里面的原件要销毁了做一些清理工作,比如清除timerlet fn=this.ref_tabs.current.handleTabClose;this.ref_tabs.current.handleTabClose=function(panel){console.log('handleTabClose',panel);let bizCom=self.getBizCom(panel);bizCom.props.foil.onStateChanged('destroy');//必须用异步,否则子函数式组件不会被调用刷新setTimeout(function(){fn.call(self.ref_tabs.current,panel);}, 0);}}
(二)主界面切换显示的语言
只要在根原件把LCID设置为响应式,改变时,tabs各个组件会刷新。
com.root.jsximport Com_Main from './com.main.jsx';
// import Com_acroMLStub from './com.acroML.stub.jsx';
export default function COM_Root(){console.log('root',acroML.browserEngine.LCID);let [LCID,setLCID]=React.useState(acroML.browserEngine.LCID);acroML.browserEngine.switchLanguage=function(){//console.log(acroML.browserEngine.LCID);setLCID(acroML.browserEngine.LCID);//console.log(LCID);}//<Com_acroMLStub>return(<Com_Main></Com_Main>);
}
相关文章:
建立无需build的react单页面应用SPA框架(2)
react-18.1.0,rc-easyui-1.2.9,babel-7.17.11 SPA还要处理的问题: (一)tabs切换事件通知 tabs切换时,自己的框架需要处理组件的生命周期,要有active/deactive,让组件能知道何时创…...
C# char曲线控件
一、char曲线显示随机数数据 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using Syst…...
远程访问本地jupyter notebook服务 - 无公网IP端口映射
文章目录 前言1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 前言 Jupyter Notebook,它是一个交互式的数据科学和计算环境,支持多种编程语言,如…...
flume系列之:记录一次消费大量Debezium数据,数据包含dml语句比较大,造成数据堆积在channel的解决方法
flume系列之:记录一次消费大量Debezium数据,数据包含dml语句比较大,造成数据堆积在channel的解决方法 一、背景二、相关技术博客三、flume层面解决方法四、debezium数据采集层面解决方法一、背景 Debezium采集了大量的数据,数据包含DMl语句,数据本身比较大。flume消费了大…...
Could not find artifact com.pageOffice:pageOffice:pom:4.3.0.2 in aliyunmaven
Could not find artifact com.pageOffice:pageOffice:pom:4.3.0.2 in aliyunmaven (https://maven.aliyun.com/repository/public) 仓库服务 阿里云云效 Maven 是什么 阿里云Maven中央仓库为 阿里云云效 提供的公共代理仓库,帮助研发人员提高研发生产效率&#x…...
2023年9月数据治理/项目管理/产品管理/商务礼仪企业内训定制
在节奏飞驰、风起云涌的企业世界中,为了企业的蓬勃发展,可以在内部或者外部挑选有经验的老师进行培训和学习。简而言之,任何一个企业想要发展,都少不了进行内训。 企业内训的好处 提高员工的技能和知识水平 通过不断地学习和培训…...
后端面试话术集锦第 九 篇:Activiti工作流面试话术
这是后端面试集锦第九篇博文——Activiti工作流面试话术❗❗❗ 1. 工作流话术 工作流这块儿,实际在工作中使用的时候,Activiti用的居多,当然还有一些其他的工作流引擎。 在网上看了也大概看了一下,其他的像JBPM以及workflow等用的情况来讲不是很多。 所以说Activiti目前…...
JS中方法、函数、属性是一个东西吗
在 JavaScript 中,方法、函数和属性是相关但不完全相同的概念。 方法(Method):在对象中,方法是对象的属性,但它的值是一个函数。方法可以通过对象来调用,并且可以访问对象的属性和其他方法。 …...
面经:微服务
文章目录 参考资料一. 微服务概述1. CAP理论2. BASE理论3. SpringBoot 与 SpringCloud对比 二. 服务注册:Zookeeper,Eureka,Nacos,Consul1. Nacos两种健康检查方式?2. nacos中负责负载均衡底层是如何实现的3. Nacos原理4. 临时实例和持久化(非临时)实例 …...
K8s 持久化存储有几种方式?一文了解本地盘/CSI 外接存储/K8s 原生存储的优缺点
当今云原生环境中,Kubernetes(K8s)已成为既定的容器编排工具。随着 K8s 的普及,存储也成为 K8s 用户关注的一个重要问题:为了满足不同的场景需求,K8s 可以支持基于不同架构的多种存储方案。这些方案间有什么…...
【MySQL】3、MySQL的索引、事务、存储引擎
create table class (id int not null,name char(10),score decimal(5,2)); insert into class values (1,zhangsan,80.5); update class set namewangwu,passwd123 where id2; select * from class where id2; drop 索引的概念 是一种帮助系统,能够更快速的查询信…...
【Hello Algorithm】链表相关算法题
本篇博客介绍: 介绍下链表相关的算法题 链表相关算法题 快慢指针回文结构链表将单向链表按某值划分为左边小,中间相等,右边大的形式复制带随机指针的链表 链表相关的算法题其实都算不上难 我们真正要考虑的是一些边界问题 事实上链表题就是在…...
自动化管理管理工具----Ansible
目录 编辑 一、Ansible概念 1.1特点 二、工作机制(日常模块) 2.1 核心程序 三、Ansible 环境安装部署 四、ansible 命令行模块 4.1command 模块 4.2shell 模块 4.3cron 模块 4.4user 模块 4.5group 模块 4.6copy模块 4.7file模块 4.8ho…...
深入理解css3背景图边框
border-image知识点 重点理解 border-image-slice 设置的值将边框背景图分为9份,图像中间的舍弃,其他部分图像对应边框的相应区域放置,上右下左四角固定,border-image-repeat设置的是除四角外其他部分的显示方式。 截图来自菜鸟教…...
【rust/egui】(六)看看template的app.rs:TextEdit
说在前面 rust新手,egui没啥找到啥教程,这里自己记录下学习过程环境:windows11 22H2rust版本:rustc 1.71.1egui版本:0.22.0eframe版本:0.22.0上一篇:这里 TextEdit 文本编辑框 其定义为&#…...
Redis内存空间预估与内存优化策略:保障数据安全与性能的架构实践
推荐阅读 AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 资源分享 史上最全文档AI绘画stablediffusion资料分享 AI绘画关于SD,MJ,GPT,SDXL百科全书 「java、python面试题」…...
【zookeeper】zookeeper集群安装
环境规划 实际的生产使用中,我们一般推荐搭建奇数多节点的zookeeper集群,如3/5/7。在本次测试中,我使用了centos7 三台服务器搭建,复用了我搭建k8s集群的环境,如下表。 IPhostname192.168.2.140k8s-m1192.168.2.141k…...
CUDA小白 - NPP(2) - Arithmetic and Logical Operations(1)
cuda小白 原文链接 NPP GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus,…...
计算机视觉-LeNet
目录 LeNet LeNet在手写数字识别上的应用 LeNet在眼疾识别数据集iChallenge-PM上的应用 LeNet LeNet是最早的卷积神经网络之一。1998年,Yann LeCun第一次将LeNet卷积神经网络应用到图像分类上,在手写数字识别任务中取得了巨大成功。LeNet通过连续使用…...
Java 复习笔记 - 面向对象篇
文章目录 一,面向对象概述二,类和对象(一)类和对象的概述(二)定义类的补充注意事项 三,封装四,就近原则和this关键字(一)就近原则(二)…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践
在电商行业蓬勃发展的当下,多平台运营已成为众多商家的必然选择。然而,不同电商平台在商品数据接口方面存在差异,导致商家在跨平台运营时面临诸多挑战,如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...
【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验
2024年初,人工智能编程工具领域发生了一次静默的变革。当字节跳动宣布退出其TRAE项目(一款融合大型语言模型能力的云端AI编程IDE)时,技术社区曾短暂叹息。然而这一退场并非终点——通过开源社区的接力,TRAE在WayToAGI等…...
2025年全国I卷数学压轴题解答
第19题第3问: b b b 使得存在 t t t, 对于任意的 x x x, 5 cos x − cos ( 5 x t ) < b 5\cos x-\cos(5xt)<b 5cosx−cos(5xt)<b, 求 b b b 的最小值. 解: b b b 的最小值 b m i n min t max x g ( x , t ) b_{min}\min_{t} \max_{x} g(x,t) bmi…...
git删除本地分支和远程分支
删除本地分支 git branch -d 分支名删除远程分支 git push origin --delete 分支名...
Redis知识体系
1. 概述 本文总结了Redis基本的核心知识体系,在学习Redis的过程中,可以将其作为学习框架,以此更好的从整体的角度去理解和学习Redis的内容和设计思想。同时知识框架带来的好处是可以帮助我们更好的进行记忆,在大脑中形成相应的知识…...
AT_abc409_e [ABC409E] Pair Annihilation
AT_abc409_e [ABC409E] Pair Annihilation 赛时没开longlong挂了。 思路 首先我们可以把这棵树转化为一颗有根树,且所有电子的都朝根节点移动。 那么接下来我们就需要选择一个最优的树根。 考虑换根dp。 但是可以发现换根时答案其实是没有变化的。 我们设 f…...
