1、react踩坑
- (1)ant table组件的对齐。刚开始以为是自己配置的 问题。结果是改变了右边的进度条的样式,然后出的问题。
- (2)dva的model使用。项目重构的时候,刚开始把所有数据都放在model里面,觉得所有东西都要用connect来弄在props上,结果发现不行。后来只把全局的数据放在model里面,把局部的数据放在自己组件里面,改变自己组件的数据,就在dispatch里面传一个callback(),在callback()里面用this.setState()来改变。
- (3)高德地图修改marker的图标为antd的图标。问题是,marker的content直接赋值为jsx值
// 坐标地址和物理地址进行转换,返回一个promise,promise的then里面的参数就是转换出来的地址值
transferLnglatToAddress(lnglat) {
return new Promise(resolve => {
const geocoder = new AMap.Geocoder(); // 当然这里还是要先引入Geocoder插件的
geocoder.getAddress(lnglat, (status, result) => {
if (result === {}) {resolve();return;} // 这个地址无法转换出中文
resolve(result.regeocode.formattedAddress);
});
});
}
async userMethod(lnglat) { // 使用上面那个转换函数,用async函数,await的返回值就是后面那个promise的resolve值
const address = await this.transferLnglatToAddress(lnglat);
}
2、导入tsx模块失败
问题:路径问题,改成绝对路径导入就行了。如:
// 需要导入的文件模块为Header.tsx
import Header from './Header'; // 失败
import Header from '@/layouts/Header'; // 成功
// const style = require('./index.less'); // 成功。如果还是不行,就用require来引入
3、img标签引入图片失败
- 使用图片:
- js中使用:如下: 直接在src里面输入链接,然后失败;需要import进来,然后引入。
- css中使用:这个就是在css modules里面使用了。可以用相对路径
../
引入,也可以用别名@,不过需要在@前面加上~
前缀
// 如下,失败
<img src='../assets/logo.png'/>
// 如下,成功
import logo from '../assets/logo.png'
<img src={logo}/>
<img src={require('./foo.png')} /> // 成功
<img src={require('@/foo.png')} /> // 成功
// a.less
.go {
border-image: url('../../../../assets/img/appIcon.jpg') 20%;
background: url(~@/foo.png); // 使用@别名来引入,不过就是需要添加~了
}
4、antd,重置组件样式
重置组件样式,需要首先用控制台找到,需要修改的组件对应的class,然后在css文件中,把对应的类名和样式包在
:global
,中,因为:global中的类名为全局类名,这个类名才不会被css modules弄成哈希字符串
// 表格样式重置。
// 下面为修改table的表头颜色和表头的字体颜色、并且去掉table的所有边框、并且把分页的文字描述部分放最左边其余部分放右边
<Table className={styles.tableStyle}></Table>
.tableStyle {
:global {
.ant-table {
border: none !important; // 去掉table最外层的边框
th, td {
text-align: center; // 文本居中
border: none !important; // 去掉table每个th和td的边框
}
}
<!--.ant-table-header {-->
<!-- background: #848996 !important; // 改变table header的背景色-->
<!-- tr th { // 如果是在这里改变背景色,而不用上面那个属性的话。在header的最后下拉条的地方,不能覆盖到背景色。所以修改背景色要用上面那个-->
<!-- color: #fff !important; // 改变table header的字体颜色-->
<!-- }-->
<!--}-->
.ant-table-thead { // 上面那个.ant-table-header类名,只有在table设置了scroll的时候才会存在。而这个.ant-table-thead类名,是一直都存在的
background: #848996 !important; // 改变table header的背景色
tr th { // 如果是在这里改变背景色,而不用上面那个属性的话。在header的最后下拉条的地方,不能覆盖到背景色。所以修改背景色要用上面那个
color: #fff !important; // 改变table header的字体颜色
}
}
.ant-pagination {
display: flex !important; // 弄成flex布局
justify-content: flex-end; // 这句是为了兼容,没有total-text文本的时候,让分页栏依然在右边
width: 100%; // 让分页占满整行
.ant-pagination-total-text {
flex: 1; // 相当于flex-grow,把所有的剩余空间全部给这个元素,其余的元素就排到这个元素的后面去了
}
}
}
.tableEvenLine {
background: #F5F5F5;
}
.tableOddLine {
background: #FFFFFF;
}
}
// 实现table的奇偶行颜色不一样,直接用rowClassName属性来判断。奇偶行给不同的样式
<Table rowClassName={(record,index)=>{index%2 === 0 ? styles.lel : styles.name}}></Table>
// 下面为修改table的滚动条的样式。不需要把下面的样式加在.ant-table-body里面,只需要放全局就好了。如果加在.ant-table-body里面需要在伪类名前面加上&,并且会出现样式错误
::-webkit-scrollbar
{
width: 8px;
height: 8px;
background-color: transparent;
}
/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track
{
-webkit-box-shadow: none;
border-radius: 10px;
background-color: transparent;
}
/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb
{
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: rgba(163,157,157,0.8);
}
5、antd清空Input、Select组件的值,以显示placeholder
这里就不能直接设置value为("")了,而需要把value设置为undefined,就可以显示出设置的placeholder了
state = {
roleValue: undefined,
}
<Select allowClear={true} placeholder="请选择角色" value={this.state.roleValue} </Select>
6、antd,table组件设置了scroll y之后,竖向的列不对齐;设置了fixed和scroll.x之后,横向的行不对齐
- 原因:antd中的表格如果设置了fixed(即设置了固定列),那么antd会多渲染出一个固定列表格,用来覆盖原始的列,这个表格里面只有被固定的列。所以在滚动条滚动的时候,上面的表格不动,只有下面的表格动。而原始表格的100%指的是scrollX中的值,固定列表格的100%指的是当前表格的宽度,所以如果给固定列设置了百分比,就有可能会出现宽度不一致的问题
- 原始表格渲染的位置为类名
ant-table-content
下面的第一个div,里面包裹了表格的header和表格的body。- 固定列表格渲染的位置为类名
ant-table-content
下面的第二个div,是原始表格的兄弟元素,里面包裹了固定列表格的所有元素。
解决列不对齐:给colunms设置width(可以是百分比),前面的都需要设置,留最后一个不设置width,让他自定义宽度。不生效的话,在添加下面样式
- 解决行不对齐:就如上面所说是由于列设置了百分比,导致固定列表格和原始表格中的列的宽度不一致。
- <1>解决方法是把fixed的列,宽度设置为固定值(比如一个固定像素)。
- <2>如果不想设置固定值,也可以用js去把两个表格的列的宽度设置为同一个值。原理为,给固定列表格对应的列加上一个类名,然后用js读取这个类名,再设置宽度为原始表格的对应列一样的宽度,就好了
// 解决列不对齐
.tablewrap {
:global {
.ant-table-tbody > tr > td,
.ant-table-thead > tr > th {
color: red;
white-space: normal;
word-wrap: break-word;
word-break: break-all;
}
}
}
// 用js解决行不对齐
// 下面为对应的jsx代码
<div className={'crud-basic-table'}>
<Table
scroll={
{ x: true }}
columns = {columns}
ref={(ref) => { this.refDom = ref; }}
/>
</div>
// 下面代码为判断传入table的columns属性,是否设置了fixed,如过设置了,就给这一列添加上一个类名。注:如果不封装,而只是手动写一个表格,可以不写下面js,直接在对应的columns里面加上对应的className就好了
if(columns && columns.length>0){
columns.forEach(col => {
if ('fixed' in col) {
if(col.fixed==='true'||col.fixed==='left'){
col.className = col.className?col.className+' antd-table-fixed-left-column':'antd-table-fixed-left-column'
}else if(col.fixed==='right'){
col.className = col.className?col.className+' antd-table-fixed-right-column':'antd-table-fixed-right-column'
}
}
})
}
// 下面就是写的js了,可以写在document.ejs中。效果为,找到对应的类名,然后把对应的宽度值,设置为对应的原始表格中列的宽度值。感觉还是有点bug,下面只是适用于固定一列的情况,如果固定两列,那么可能代码就不是这样写了
<script>
//解决Antd 列空白间隙问题
//表格固定列宽度设置为底层被覆盖的固定列宽度
var crudTable = document.getElementsByClassName('crud-basic-table');
for (var i = 0; i < crudTable.length; i++) {
var ct = crudTable[i];
//左侧固定列
var lf = ct.getElementsByClassName('ant-table-fixed-left');
if(lf.length>0){
var lfColumn = lf[0].getElementsByClassName('antd-table-fixed-left-column');
var fixedLfCol = ct.getElementsByClassName("ant-table-fixed-columns-in-body antd-table-fixed-left-column");
for (let j = 0; j < lfColumn.length; j++) {
lfColumn[j].style.width = fixedLfCol[j].offsetWidth+"px";
}
}
//右侧固定列
var rg = ct.getElementsByClassName('ant-table-fixed-right');
if(rg.length>0){
var rgColumn = rg[0].getElementsByClassName('antd-table-fixed-right-column');
var fixedRgCol = ct.getElementsByClassName("ant-table-fixed-columns-in-body antd-table-fixed-right-column");
for (let j = 0; j < rgColumn.length; j++) {
rgColumn[j].style.width = fixedRgCol[j].offsetWidth+"px";
}
}
}
</script>
7、antd,table组件把其中一列的值设置为图片
解决办法:直接返回一个图片,把图片的width设置为100%就好了
{title: '广告图片', dataIndex: 'fileInfo', width: '10%',
render: (text, record, index) => {
const url = record..thumbnailFilePath;
return <img src={url} alt='图片.png' style={
{width: '100%'}} />; // 就这里直接返回这个图片就好了
}},
8、Select组件,DatePicker等组件的长度会受到里面的Input框样式影响
直接在Select组件,DatePicker等组件上面设置width,那么设置的是它整个组件的width;而不是显示在页面上面的框的input长度,要设置那个显示在页面的组件里面的input的长度,还需要在里面再设置Input组件的长度来实现。如下:
.popModelTimeBox { // 这个为一个DatePicker组件,是直接在它上面设置的class。但是设置的width是整个组件的width(不代表显示出来的时间选择框的width)
width: 72.7%;;
Input { // 这个长度设置的就是DatePicker组件,里面的时间选择框的长度了
width: 100% !important;
}
}
// 一般情况下,直接在组件上面设置width也可以实现需求了。一般就先用这个方法设置样式,然后再用上面那个方法
<Col span={5} className={styles.dealerList}>
<span>品牌:</span>
<Select style={
{width: '72%'}}></Select>
</Col>
9、初始化一些值的时候,使用this.state
首先,在state里面直接读取this.state是读取不到的。而在componentDidMount的时候是可以获取到state的。另外,在render()方法的return上面,是可以获取到this.state的,一般把return出去的组件里面的配置信息就写在render里面。
// 下面例子
construct(){
super(props);
this.state={
go: 111,
what: this.go, // 这里会报错,undefined,因为state还没初始化完成
showTotal: () => {
console.log(this.state.go); // 这里是可以的
}
};
}
// 下面例子就可以了,放到componentDidMount里面去
construct(){
super(props);
this.state={
go: 111,
what: null, // 在componentDidMount里,用setState去修改,就好了
};
}
componentDidMount() {
this.setState({
what:this.state.go // 到这里来修改
});
}
render() {
const paginationConf = {total: this.state.total,} // 这里也是可以直接获取到this.state的值的
return (<Table pagination={paginationConf}></Table>);
}
10、关于设置proxy跨域
如果刚开始mock的接口和跨域的是一样的,则会首先请求mock的接口。
11、antd里面组件有很多配置信息的时候,配置写在变量里面
最新发现写法就是把组件的配置依然是写在render里面,不过如果配置信息很多,那么配置不写在组件上面,而是独立出来;配置信息很少,那么还是写在组件上面。如下:
class demo extends PureComponent {
render() {
// 这个props就是配置信息了
const props = {
name: 'file',
action: 'https://www',
headers: {
authorization: 'authorization-text',
},
};
return (
// 把props直接用拓展运算符展开。这个写法就很直观了,很方便查看
<Upload {...props}></Upload>
);
}
};
12、实现弹出一个modal,这个modal为整个图片
这个简单说就是把modal的背景替换为一个图片,就是这么简单
// 新增编辑里面,预览按钮的弹出框出现的样式
.previewModalStyle {
:global {
.ant-modal-content {
height: 41.3vw;
border-top-left-radius: 4.6% 7.78%;
border-top-right-radius: 4.6% 7.78%;
border-bottom-left-radius: 4.6% 7.78%;
border-bottom-right-radius: 4.6% 7.78%;
background: #152036 url('../../../../assets/img/previewTemplate.png') 0 0 no-repeat;
background-size: cover;
color: #fff;
}
.ant-modal-body {
width: 100%;
// height: 94.1%;
height: 100%;
padding: 15.84% 3.36% 0 14.45%;
margin: 0;
overflow: hidden;
}
}
}
<Modal {...previewModalProps} className={styles.previewModalStyle}>
<Row type='flex'>
<Col span={24} style={
{fontSize: '16px',marginBottom: '20px'}}>
<span style={
{color: '#fff',marginRight: '20px'}}>{title}</span>
<span style={
{color: 'rgb(141,215,230)'}}>{time}</span>
</Col>
<Col span={24} style={
{height: '24.78vw',fontSize: '16px',color: '#fff',overflow: 'auto'}}><div ref={contentRef} /></Col>
</Row>
</Modal>
13、react 组件销毁与bug规避问题
在react 的jsx中,使用 && 运算符,可以让后面的组件销毁或者显示,这样相当于vue里面的v-if(在一定情况下,可以优化性能或者浪费性能),不过 确实可以规避很多问题,降低了代码的复杂的
// 下面 goVisible 为true的时候,展示后面组件;goVisible为false的时候,后面组件被销毁
{
goVisible && <PageContentWrapper
loading={loading}
buttonlist={[]}
dispatch={dispatch}
doQuery={doQuery}
isReload={isReload}
renderSearchForm={renderSearchFormMemo}
tableOpts={tableOpts}
autoQuery={false}
/>
}