码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • react-antd项目,一个多tab页面,共用一个title相同的table表格,并且在切换tab时实现数据更新


    一、前言

    最近因为项目要求,开始学习并且使用React和Ant Design框架。在前端开发过程中,遇到这样一个页面:有多个tab,每个tab下都是一个table表格来进行数据展示。但,每个table的title都是一样的,如何进行表格的渲染和对应数据的展示就值得开发人员考虑。下面,我们一起来瞧瞧。

    二、性能优化和逻辑分析

    2.1、性能优化

    在开发中,最大程度上对性能进行优化,是开发人员的不懈追求。对于前端开发而言,操作尽可能少的DOM的,是页面性能优化的一个重要部分。
    为什么这样说呢,来看看下面这个简化版的,浏览器输入url到网页显示的整个过程就明白了:

    • 浏览器输入url并回车
    • 域名解析
    • 发起TCP三次握手
    • 发送HTTP请求
    • 服务端响应请求,浏览器得到html代码
    • 浏览器解析html代码,并请求html代码中的资源
    • 页面渲染呈现给用户

    “页面渲染呈现给用户”这最后一步,又是这样一个过程:

    • 浏览器把获取到的html代码解析成1个DOM树,html中的每个标签都是DOM树中的一个节点,根节点就是document对象。DOM树中包含了所有html标签
    • 浏览器解析所有样式(解析成样式结构体:CSSOM树),在解析的过程中去掉浏览器不能识别的样式
    • DOM树和CSSOM树组合后构建render tree
    • 等render tree构建完成后,计算像素坐标等一些列准备工作
    • 浏览器根据此来绘制页面

    那么,既然每个table的title都一样,只是渲染的数据有不同,基于性能优化的考虑,我让这个页面的每个tab都共用一个table,每次点击不同的tab,根据此tab的key值,调用不同的后端数据接口,处理数据并完成数据更新。
    这样,最大程度的减少了DOM的渲染,达到性能优化的目的。能推出,这个table表格越复杂,优化的效果越好,因为减少了更多重复的DOM渲染(这是不必要的)。

    2.2、逻辑分析

    既然已经从性能优化角度分析除了最好的方式是减少DOM渲染,那么,最直接的方法就是,在react的对应组件中(主要使用了antd的Tabs、Table组件),直接让Table组件和Tabs组件平级即可。为了更清楚,直接上代码:

    //  我用的是函数组件
    import { ..., Table, Tabs, ... } from 'antd';
    import React, { useEffect, ..., useState } from 'react';
    ...
    const onChange = (key: string) => {
    	if (key === '1') {
    		//  这里写调用接口和处理数据的逻辑代码
    		...
    	}else if key === ‘2’) {
    		//  这里写调用接口和处理数据的逻辑代码
    		...
    	}...
    }
    ...
    const App: React.FC = () => {
    	...
    	return (
    	//  让Table组件和Tabs组件平级(这里的结构是关键)
    		<>
    			
    				...
    			
    			
    				...
    		
    	)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    三、遇到的问题及解决

    大的思路想好之后,代码开发过程中,我在更新Table的datasource过程中又遇到了问题。预想的是,进入到这个页面时,默认选中第一个tab,调第一个tab的数据接口,然后将数据赋值给Table的datasource,让表格对其进行展示。

    3.1、遇到的问题

    1、写在useEffect中的接口调用,通过浏览器控制台的Network,看到这个接口在不断的调用,导致点击别的tab,数据在瞬间更新后又被useEffect钩子中的第一个tab数据冲掉;

    2、datasource数据赋值成功了,但是Table表格中数据却没有更新。

    3.2、问题分析

    问题1:useEffect的函数在不断地被执行,导致同一个接口被不断的调用,我第一反应就是去查阅useEffect钩子的说明文档,果然被我找到了原因,下面贴几张官方文档的截图来说明:
    在这里插入图片描述
    在这里插入图片描述
    下面这张图是最主要的原因
    在这里插入图片描述
    问题2:Table的dataSource 更新,Table未重新渲染。为什么React不重新渲染DOM呢?从这个思路出发,在查阅了React的DOM的重新渲染及之后,在看我的给datasource赋值代码,(才开始,我没有用useState钩子函数,而是直接定义了一个空数组变量给datasource使用)发现了问题:

    //  这是我有问题的赋值代码:
    ...
    const tab2Datasource = async () => {
    	const apiRes = await 接口调用函数名;
    	if (apiRes) {
    	//  假设这块的apiRes已经被我处理成我需要的数据格式了
    	//  注意这块的赋值代码,我是直接“=”赋值的,对于数组这种复杂数据类型来说,这只是改变了它在栈内存中的指针,并没有实质性的改变其堆内存中的数据。
    	//  但就是因为指向了一个地址,React认为虚拟DOM并没有改变,因此,不会重新渲染页面。
    	//  这就会导致Table组件的dataSource改变了,但是Table并没有重新渲染
    		tableData = apiRes
    	}
    }
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.3、问题解决

    再分别找出bug的原因之后,修改起来就很简单了。直接上代码:
    问题1:解决接口函数在useEffect钩子中被无限调用的问题

    //  这是原来的bug代码:
      useEffect(() => { tab1Datasource() });
     //  给useEffect钩子中加上空数组的参数即可
      useEffect(() => { GetMyToDoFlowList() }, []);
    
    • 1
    • 2
    • 3
    • 4

    问题2:解决datasource数据更新了但Table不更新的问题

    //  原来的bug代码
    见“3.2、问题分析”的代码
    //  成功修改Bug后的代码
    ...
    import React, { useEffect, ..., useState } from 'react';
    ...
    const App: React.FC = () => {
    	...
    	//  1、使用useState钩子函数
    	const [tableData, setTableData] = useState(Array);
    	//  2、重新改变数组的赋值方式
    	//  解决原理也很简单,新建一个Array指向不同地址,再赋值,这样React就会认为需要重新渲染Table了
      	const tab2Datasource = async () => {
        	const apiRes = await 接口调用函数名;
       		if (apiRes) {
          		const tableDatas: DataType[] = [];
          		const datas: DataType[] = [
            		{
             			key: '1',
              			name: 'John Brown',
              			age: 32,
              			address: 'New York No. 1 Lake Park',
    		        },
           	 ...
          		];
          		datas.forEach((item) => {
    	        	tableDatas.push(item);
          		});
          		setTableData(tableDatas);
        	} else {
          		console.log('代办工作数据请求失败!!!');
        	}
      	};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    四、说明

    参考链接:
    React官方文档之使用 Effect Hook
    JS的浅拷贝和深拷贝的剖析以及部分实现方法
    React Table dataSource 更新,Table未重新渲染

    欢迎大家一起讨论、学习

  • 相关阅读:
    f12工具
    深度学习·理论篇(2023版)·第004篇深度学习和概率论基础01:使用大白话举例说明条件概率独立概率+期望值方差+协方差+熵和平均编码长度的关系
    JavaScript中的map()和forEach()方法有什么区别?
    创建单链表,并对单链表的数据进行增、删、改、查、数据输入、打印等操作(C++)
    AIGC绘画设计——midjourney有哪些好用的关键词?
    Vue 2.0/3.0
    泛型的理解和好处
    亚马逊测评安全吗?
    接龙管家-Python自动打卡(续)获取接龙管家token
    关于多传感器融合方法的总结与思考
  • 原文地址:https://blog.csdn.net/BigFamer/article/details/126303740
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号