资源日历 踩坑记(二)

目录

ES6相关

对象引用问题

描述: 在做一个操作的时候,发现数据总是出问题,后来才发现,在涉及到对象的时候,自己就直接把对象赋值过去了。所以几个变量实际上操作的是一个对象。(有两次都是这个原因,而且花费了很多时间找bug。)

解决: 使用Object.assign()对对象进行复制,还有,遇到对象进行操作的时候一定要谨慎。

一组array里面存放object的,匹配projectId

描述: 通常有这么一个需求,有一个数组(a)里,存放了很多对象,然后需要将每个对象里的projectName拿出来进行渲染到AutoComplete组件里,然后有另一个数组(b)里,同样,它也存放了很多对象,然后也需要将每个对象里的username拿出来渲染到AutoComplete组件里。最后当用户在2个AutoComplete里面选择或者输入了值后,然后再将它们和2个数组里的projectNameusername进行匹配,如果匹配成功,就将projectIduid拿出来, 然后进行相应的数据处理。

解决办法:

function getSelectProject(projectName) {
  const projects = this.props.project.data;
  return projects.filter(item => item.projectName === projectName);
}

const inputProjectName = values.projectName; 
const selectProject = getSelectProject(inputProjectName);

if (!selectProject) {
  return;
}
const { projectId } = selectProject;

在上面的描述里,加上一个需求

描述: 在上面的需求里,终究只有2个AutoComplete里面需要进行匹配。那么如果我们将上面的数据当作一行, 而有很多这样的行在table里面,那么又该如何去实现呢?

解决办法:

  • 先判断是否所有的projectNameusername都是对的。
  • 如果都是对的,然后再得到相应的projectIduid
  • javascript foreach break
  • 为什么不使用foreach看上面。
const projectMatch = inputProjectNames.every(item => dbProjectNames.includes(item));
if (!projectMatch) {
  return false;
}

inputProjectNames.every((item1) => {
  dbProjects.every(item2) => {
    if (item1 === item2.projectName) {
      projectIds.push(item2.projectId);
      return false;
    }
    return true;
  }
  return true;
});

数据格式化

描述: 需要将下面的这种数据格式转换为另外一种:

const array = [
  {
    date: '2017-01-02', 
    uid: 'yuzf',
    hour: 8,
  },
  {
    date: '2017-01-02', 
    uid: 'yuzf',
    hour: 5,
  },
  {
    date: '2017-01-03', 
    uid: 'hwy',
    hour: 1,
  },
  {
    date: '2017-01-03', 
    uid: 'hwy',
    hour: 2,
  },
];

const newArray = [
  {
    date: '2017-01-02', 
    uid: 'yuzf',
    hour: 13,
  },
  {
    date: '2017-01-03', 
    uid: 'hwy',
    hour: 3,
  },
];

解决办法: 第一种是使用双重循环,第二种是不使用双重循环,使用一个循环就可以了。看代码:

// method1
for (let i = 0; i < array.length; i++) {
  let isOk = false;
  for (let j = 0;j < newArray.length; j++) {
    if (array[i].uid === newArray[j].uid && 
      array[i].date === newArray[j].date) {
      newArray[j].hour += array[i].hour;
      isOk = true;
    }
  }
  if (!isOk) {
    newArray.push(array[i]);
  }
}

// method2
let obj = {};
let arr2 = [];
array.forEach((item, index) => {
  if (obj[item.uid+item.date]) {
    obj[item.uid+item.date].hour += item.hour;
  } else {
    obj[item.uid+item.date] = item;
  }
});

for (let i in obj) {
  arr2.push(obj[i]);
}
console.log(arr2);

includes

描述: includes方法用于判断数组里是否包含某一个值,如果包含则发挥true,否则false。注意,当测试它用来判断对象的时候,特别要注意,因为Object是引用类型,如果判断是否包含的话,这里是判断的是否为同一个对象,如果是同一个对象,则返回true,否则是false。

react相关

react的state

描述: state里会有一个元素是数组,经常要对这个数组进行增加新元素。一般方法如下:

const { isActive } = this.state;
this.setState({
  isActive: [...isActive, date], 
});

antd相关

我也不是特别明白的问题

// Error
<Button onClick={this.onCopy(index)} />

// Right
<Button onClick={() => this.onCopy(index)} />

// Error
getDate={this.getDate}

// Right
getDate={() => this.getDate}

同时获取多个Input的值

描述: 几个Input, 使用antd提供的API, 比如onChange onSelect等方法,它们的参数是当前change或者select的值。但是我每次onChange或者onSelect的时候我要获取同时判断2个Input的值怎么办呢? 如果使用state或者说是通过antd的form提供的API获取的多个Input的值,并不是实时的,它们都类似于state的异步一样的,也就是说,比如输入a, onChange的时候获取的是空的,再输入b,onChange的时候获取的是a, 再输入c,onChange的时候获取的是ab, 也就是说是异步的。

解决办法: 最后的解决办法是将2个Input的数据存到state里, 然后onChange的时候,获取当前的参数值,是实时的,而另一个值是放到state里面的,因此去state里去取就可以了。

AutoComplete渲染报错

描述: 使用AutoComplete的是否,要自定义数据,因此需要使用map()去重新写子组件,但是报错了(key 重复)。

解决办法: 因为是key使用的是人名,人名有重复的,因此要么使用index, 要么使用其他办法。

AutoComplete搜索显示

描述: AutoComplete默认搜索时,只有当全部匹配的时候才会显示,如果想要部分匹配的话请看下面。

解决办法: 使用filterOption参数, 它的值是一个function, 比如下面这样:

export function filterOption = (v, option) => {
  const source = option.props.children.toUpperCase();  
  return source.indexOf(v.toUpperCase() !== -1);
};

modal框不显示

描述: 使用antd的modal框,但是modal框不显示。

原因: 必须为modal组件设置visible, 它才会显示。

table渲染(大坑)

描述: modal框里是一个table, table里每一行都有AutoComplete以及Input可以对table进行编辑,然而table里的数据是提供的API:dataSource, 我每次对table里的AutoComplete或者Input进行直接编辑的时候,必须得修改dataSource的值,但是它的值一旦修改了,整个table都要重新渲染,一旦重新渲染,输入框就失去了焦点。也就是说,每输入一下就失去了焦点。

解决办法: 最终,我的解决办法是优雅降级,将AutoComplete的事件触发改为onSelect, 将Input修改为官方的那种需要点击编辑图标才能进行编辑,这样table重新渲染的时候,即使失去了焦点也不会影响使用。

我在网,上找到别人和我遇到的一样问题的地址: 点击这里

推荐: 然后另一个降级的办法是: 将Input写为非受控组件,onBlur失去焦点的时候再触发视图刷新, 这样就可以了。代码如下:

// This is not work, but I don't know why
<AutoComplete
  onBlur={console.log('ok')}
/>

// This is good.
constructor() {
  this.handleBlur = this.handleBlur.bind(this);
}

handleBlur() {
  console.log('blur');
}

<AutoComplete
  onBlur={this.handleBlur}
/>

<Input
  onBlur={this.handleBlur}
/>

第三种方法: 这是后面改的时候发现的,但是这是一个坑,只能用一次。为什么这么说呢?因为违背了react里的state的设计原则。解决办法如下:

constructor() {
  const { tableData } = this.props.resourceState;
  this.state = {  tableData };
}

// 这里是table行里的组件的操作
onProjectChange(index, value) {
  const { tableData } = this.state;
  const copyTableData = tableData.slice();
  copyTableData[index].projectName = value;
}

render() {
  const { tableData } = this.state;
  <Table
    dataSource={tableData}
  />
}

再次强调,不到万不得已,是不可以这么做的,这违背了react的设计原则

table的渲染(rowkey)

描述: 使用antd的table时,控制台报了错,原来是要求table的每一行数据都需要指定唯一的一个值,有点儿类似于react要求使用map的时候,子组件都要指定key。但是我对table进行了增加、删除、修改操作,因此我不能为rowkey指定为index。

解决办法: 最后我在找了一个npm包,是关于uuid, 设置<Table rowkey="uuid" />, 这样就保证每一行都有唯一的key了,同时也要注意,每一行也需要设置key

mongoose相关

关于查询

描述: 当我还没有为表增加任何一条数据的时候,表此时还没有生成。因此在做查询操作的时候,打印出来的error是null, 说明没有error, 而为什么没有打印出doc是因为本身就没有查询出来东西。因此,要必须先插入至少一条数据才可以看到有表生成,以及查询操作才会出来结果。

eslint相关

描述: Expected parentheses around arrow function argument having a body with curly braces arrow-parens, 意思是说箭头函数的参数需要一个括号()

记自己傻逼

InputNumber组件在modal里的table里没有显示出来

原因: 自己将render写成了rener, 控制台没有报错,真的很傻逼。

打包的数据出错

描述: 自己还以为是后台进行数据操作的时候会存在异步,后来才发现数据打包的时候就出错了。一步一步的走到上层的组件,结果发现在最外层组件,数据就出错了。

原文地址:https://www.cnblogs.com/yzfdjzwl/p/6946504.html