当前位置:   article > 正文

前端(三)React踩坑记录

前端(三)React踩坑记录

一、引言

        作者最近新的平台项目是需要用react的,和vue区别还是比较大的,这里记录下踩坑和使用经验。

二、环境

        框架:antd

        依赖:

  1. "dependencies": {
  2. "@ant-design/icons": "^4.7.0",
  3. "@ant-design/plots": "^1.0.9",
  4. "@aws-sdk/token-providers": "3.501.0",
  5. "@babel/helper-string-parser": "^7.22.5",
  6. "@loadable/component": "5.15.3",
  7. "@rjsf/antd": "^5.13.0",
  8. "@rjsf/core": "^5.13.0",
  9. "@rjsf/utils": "^5.13.0",
  10. "@rjsf/validator-ajv8": "^5.13.0",
  11. "@testing-library/jest-dom": "^4.2.4",
  12. "@testing-library/react": "^9.3.2",
  13. "@testing-library/user-event": "^7.1.2",
  14. "ajv": "^8.12.0",
  15. "antd": "^4.20.0",
  16. "axios": "^0.21.1",
  17. "babel-eslint": "^10.1.0",
  18. "bignumber.js": "^9.1.2",
  19. "core-js": "^3.20.3",
  20. "cross-env": "^7.0.2",
  21. "customize-cra": "^1.0.0",
  22. "diff_match_patch": "^0.1.1",
  23. "ejs": "^3.1.3",
  24. "enzyme": "^3.11.0",
  25. "express": "^4.17.1",
  26. "json-bigint": "^1.0.0",
  27. "lodash": "^4.17.21",
  28. "mockjs": "^1.1.0",
  29. "moment": "^2.29.4",
  30. "nodemon": "^2.0.4",
  31. "qrcode": "^1.5.1",
  32. "qrcode.react": "^3.1.0",
  33. "rc-queue-anim": "^2.0.0",
  34. "rc-texty": "^0.2.0",
  35. "rc-tween-one": "^3.0.6",
  36. "react": "^17.0.2",
  37. "react-app-rewired": "^2.1.8",
  38. "react-dom": "^17.0.2",
  39. "react-router-dom": "^5.2.0",
  40. "react-scripts": "4.0.2",
  41. "react-transition-group": "^4.4.2",
  42. "styled-components": "^6.1.8",
  43. "tslib": "^2.4.0",
  44. "typescript": "~3.7.2",
  45. "xlsx": "^0.18.5",
  46. "yarm": "^0.4.0",
  47. "yarn": "^1.22.19"
  48. },

三、React踩坑

1、编译

        不知道是react本身编译规则严苛,还是公司的pipline设定,代码里面编译的时候不允许有未使用的变量,不允许使用未导入的组件

        举个例子,如果使用了分页,但是没有导入Pagination,编译报错

  1. import {Button, Modal, Layout, messag, Space, Table, Cascader, Input} from 'antd';
  2. <Pagination onChange={this.onPageChange} total={this.state.totalSize}/>

        如果标识了参数但是没有用,编译报错

  1. onPageChange = (page, size) => {
  2. this.setState({page: page});
  3. this.loadList();
  4. };

2、变量延迟

        这是很坑的,设置变量值之后居然没有变,是有延迟的,所以当设置完之后需要间隔一下再去使用,作者就出现了点击第二页显示第一页

  1. onPageChange = (page, size) => {
  2. this.setState({size: size});
  3. this.setState({page: page});
  4. setTimeout(() => {
  5. this.loadList();
  6. }, 5);
  7. };

3、分页

        根据官网显示,列表数量超过50才会显示数量选择器,除非你显式指定,但是问题是有必要组件自己做这种判断吗,看的人一头雾水

4、上传文件多次触发

        这里就是上传组件里面嵌套了一个按钮,不知道为什么选中文件之后会多次触发fileChange

,fileChange调用upload然后后面两次的文件还是空的,然后就告警两次

  1. <Upload
  2. loading={this.state.uploadLoading}
  3. id='modify-excel-input'
  4. className='modify-excel-input'
  5. accept='.xls,.xlsx'
  6. action={getUploadFileUrl()}
  7. beforeUpload={this.checkFile}
  8. onRemove={this.deleteFile}
  9. onChange={this.fileChange}
  10. maxCount={1}
  11. >
  12. <Button
  13. loading={this.state.uploadLoading}
  14. icon={<UploadOutlined/>}>上传</Button>
  15. </Upload>
  16. upload = () => {
  17. console.log('RetrySelect upload');
  18. if (this.state.fileList == null || this.state.fileList.length <= 0
  19. || this.state.fileList[0].response == null || this.state.fileList[0].response.length <= 0) {
  20. message.error("请上传文件");
  21. return;
  22. }
  23. }

        所以作者就在fileChange里面加了判断看文件是否为空

  1. fileChange = ({fileList: newFileList}) => {
  2. if (newFileList == null || newFileList.length <= 0
  3. || newFileList[0].response == null || newFileList[0].response.length <= 0) {
  4. return;
  5. }
  6. console.log("文件列表: ", newFileList);
  7. this.state.fileList = newFileList;
  8. this.upload();
  9. }

 5、绑定本地变量

        输入框、选择框之类的组件需要和本地变量进行绑定,但是他就不像vue简单的设置v-model就可以,他需要识别变更方法

        还必须bind(this),不然绑定本地变量的话根本没法写进输入框,官网也没什么说法,chatGpt也不知道,让人一头雾水

  1. <Input
  2. maxLength={100}
  3. value={this.state.subject}
  4. style={{width: '350px'}}
  5. onChange={this.changeSubject.bind(this)}
  6. placeholder="请输入"/>
  7. changeSubject = (event) => {
  8. this.setState({subject: event.target.value});
  9. };

四、使用

        这里再介绍一些基础使用

1、动态列

        如果表格数据不固定,就可以后端返回列名

  1. const processedColumns = resData.columns.map(column => {
  2. return {
  3. ...column,
  4. dataIndex: column.dataIndex,
  5. title: column.title,
  6. width: '200px',
  7. };
  8. });
  9. this.setState({columns: processedColumns})
  10. <Table
  11. columns={this.state.columns}
  12. dataSource={this.state.list}
  13. bordered
  14. scroll={{x: 1500, y: 'calc(100vh - 350px)'}}
  15. pagination={false}
  16. />

2、超长展示

        超过一定长度展示省略号,悬浮展示所有

  1. {
  2. title: 'response',
  3. dataIndex: 'response',
  4. width: '180px',
  5. render: (text) => {
  6. return <Tooltip placement="top" title={text}>
  7. <div style={{
  8. width: 150,
  9. overflow: "hidden",
  10. textOverflow: "ellipsis",
  11. whiteSpace: "nowrap"
  12. }}>{text}</div>
  13. </Tooltip>
  14. }
  15. },

3、跳转携带参数

        原始页面把参数直接缀在路径后面就可以,如果是很多参数可以用json转字符串,到目标页面进行解析

  1. const w = window.open('about:blank');
  2. w.location.href = '#/detail/' + record.id;

        目标页面通过匹配参数拿到

  1. constructor(props) {
  2. super(props);
  3. this.state = {
  4. loadingExecute: false,
  5. id: props.match.params.id,

        参数的名字是由配置url页面决定的

  1. {
  2. path: '/detail/:id?',
  3. name: 'detail',
  4. pageId: '1010',
  5. authPass: true,
  6. },

4、弹窗

        他的弹窗使用visible属性判断是否展示的,在render里面定义号,然后通过更新本地变量进行展示隐藏

  1. <Modal visible={this.state.executeVisible} onOk={this.goExecute.bind(this)}
  2. onCancel={this.handleCancel.bind(this)}
  3. footer={[
  4. <Button key="submit" type="primary" onClick={this.goExecute.bind(this)}>
  5. 确认
  6. </Button>,
  7. <Button key="back" onClick={this.handleCancel.bind(this)}>
  8. 取消
  9. </Button>
  10. ]}>
  11. <div style={{marginTop: '20px'}}>
  12. <span style={{width: '80px', marginRight: '10px'}}>工单</span>
  13. <Input
  14. maxLength={100}
  15. value={this.state.woCode}
  16. style={{width: '350px', marginRight: '20px'}}
  17. onChange={this.changeWoCode.bind(this)}
  18. placeholder="请输入"/>
  19. </div>
  20. <div style={{marginTop: '20px'}}>
  21. <span style={{width: '80px', marginRight: '10px'}}>主题</span>
  22. <Input
  23. maxLength={100}
  24. value={this.state.subject}
  25. style={{width: '350px'}}
  26. onChange={this.changeSubject.bind(this)}
  27. placeholder="请输入"/>
  28. </div>
  29. </Modal>

5、获取浏览器信息

        主要是获取域名和cokkie

  1. const cookie = document.cookie.split(';')
  2. const host = document.domain.toLowerCase()

五、总结

        不同的前端使用起来区别挺大的,作者感觉还是vue好用一些,不过react好像更加国际化一些,公司整体还是偏向用react。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/376652
推荐阅读
相关标签
  

闽ICP备14008679号