Skip to content

1.react 实现 v-if 类似的功能

jsx
function MyComponent({ condition }) {
  return (
    <div>
      {condition ? <div>条件为真时的内容</div> : <div>条件为假时的内容</div>}
    </div>
  );
}

或者

jsx
export default class MyComponent extends Component {
  render() {
    const { condition } = this.props;
    <div>
      {/*这里就相当于:
      		<template v-if="condition">
      			<div>条件为真时的内容</div>
      		</template>
      		<template v-else>
      			<div>条件为假时的内容</div>
      		</template>
      	其实 react 的写法反而更加方便,在 jsx 里面是可以随意书写 js 表达式的
      */}
      {condition ? <div>条件为真时的内容</div> : <div>条件为假时的内容</div>}
    </div>;
  }
}

2.把 props 赋值给 state(动态)

注意:把 props 赋值给 state 只能在 componentDidUpdate 这个钩子里面进行

js
//要获取更新后的 props,一定是在这个钩子里面!
componentDidUpdate(prevProps) {
  //prevProps是上一次的 porps,这个代码的意思就是这次的props的 data 属性的 id 和上一次不一样的话就进行重新的赋值!
  if (this.props.data.id !== prevProps.data.id) {
    this.setState({
      data: {
        time: this.props.data.time,
        title: this.props.data.title,
        notes: this.props.data.notes,
      },
    });
  }
}
js
componentDidUpdate(prevProps) {
  if (prevProps.allData !== this.props.allData) {
    this.setState({ allData: this.props.initialValue });
    // console.log(this.state.allData);
  }
}

失败的情况(动态更新的 props 失败的情况)

如果不是动态的 props,那么是可以的:——> 静态可行

js
componentDidMount() {
  // 最新的 props 指的是更新流程下的,更新不会调用这个钩子(只有在第一次挂载时调用)
  // 所以在这里获取不到 最新的props
  console.log(this.props);
}

如果不是动态的 props,那么是可以的:——> 静态可行

js
//在构造器里面赋值的话,props 不是最新的,跟componentDidMount的原理一样
constructor(props) {
     super(props);
     console.log(props);
     this.state = {
       data: {
         time: props.data.time,
         title: props.data.title,
         notes: props.data.notes,
       },
     };
}

这个任何时候都不行:

js
 render() {
    //console.log(this.props);
    //在 render 里面有最新的 props 值(因为每次更新都会调用),但是不能使用 setState 方法(因为没有办法写终止条件)!所以也不能在这里给 state赋值
    // this.setState({
    //   data: {
    //     time: this.props.data.time,
    //     title: this.props.data.title,
    //     notes: this.props.data.notes,
    //   },
    // });
 }

接收 props 不需要赋值 state 的情况

当 props 的数据仅是作为展示的时候,不进行更改,那么就没必要进行状态的存储,也就不用赋值给 state

直接在 render 里面进行使用即可:

jsx
render() {
  const {users,isFirst,isLoading,err} = this.props
  return (
    <div className="row">
      {
        isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
        isLoading ? <h2>Loading......</h2> :
        err ? <h2 style={{color:'red'}}>{err}</h2> :
        users.map((userObj)=>{
          return (
            <div key={userObj.id} className="card">
              <a rel="noreferrer" href={userObj.html_url} target="_blank">
                <img alt="head_portrait" src={userObj.avatar_url} style={{width:'100px'}}/>
              </a>
              <p className="card-text">{userObj.login}</p>
            </div>
          )
        })
      }
    </div>
  )
}

3.用 componentDidUpdate 实现计算属性的效果

这里利用了 prevState 这个属性

componentDidUpdate 钩子里面一定要有终止条件

js
componentDidUpdate(prevProps, prevState) {
  //这里实现了类似计算属性的功能,动态计算numAlready和numWill
  //注意:一定要判断prevState.numAlready !== num1 ||prevState.numWill !== this.state.num2,否则一直使用 setState方法的话,就会一直更新,这个回调会永远进行下去,就栈溢出了!
  let num1 = 0;
  this.state.allData.forEach((e) => {
    if (e.isDid === true) {
      num1 += 1;
    }
  });
  const num2 = this.state.allData.length;
  if (prevState.numAlready !== num1 || prevState.numWill !== num2) {
    this.setState({
      numAlready: num1, //已经完成的数量
      numWill: num2, //未完成的数量
    });
  }
}

4.合并对象:覆盖效果

js
//Object.assign合并两个对象,后面的会把前面已有的覆盖,没有的就添加到前面!
const newItem = Object.assign(this.state.editData, data);
//...合并对象和Object.assign是一样的,同样后面的会把前面已有的覆盖
const newItem = Object.assign(this.state.editData, data);

5.map 更改对象数组

更改对象数组中的某一整项:

js
const result = this.state.allData.map((e) => {
  if (e.id === this.state.editData.id) {
    return newItem; // 替换为新项
  }
  return e; // 保持原项
});
// 下面这样不行:因为forEach 方法在遍历数组时没有返回值,它只是对每个元素执行回调函数而已,并且不会修改原数组。这也是forEach和 map 的重大区别!
// const result = this.state.allData.forEach((e) => {
//   if (e.id === this.state.editData.id) {
//     e = data;
//   }
// });

要修改对象数组中满足条件的一项的某个属性值:

js
const updatedArray = originalArray.map((item) => {
  if (item.id === targetId) {
    return { ...item, propertyToModify: newValue };
  }
  return item;
});

6.state 的属性是一个对象时的更新赋值策略

需要把整个对象一起赋值,不能单独赋值某一个属性

js
this.setState({
  data: { ...this.state.data, [type]: event.target.value },
});
//这样不行,会把其他的属性弄没
// this.setState({
//   data: { [type]: event.target.value },
// });
// console.log(this.state.data);'

7.radio 单选框的策略

一般不要给 radio 加 name 否则就变成和其他的是一组的了,就只能有一个被选中

html
<input type="radio" checked={this.state.isAllChecked} readOnly onChange={() =>
this.complete(e.id)}/>

checked 属性是控制是否被选中的状态的

对应的 css 伪类状态为 input:checked

自己构建自定义样式的 radio 的策略

注意:这里不在 radio 上使用 onChange 事件,而是在 span 上使用 onClick 事件

jsx
<div className='radio-container'>
  {/* 一定不要给 radio 加 name 否则就变成大家是一组的了,就只能有一个被选中 */}
  <input type='radio' checked={e.isDid} readOnly />
  <span className='radio-custom' onClick={() => this.complete(e.id)}></span>
</div>
css
/* 自定义单选框样式 */
.radio-container {
  display: inline-block;
  vertical-align: middle;
  cursor: pointer;
  /* margin-right: 10px; */
}

.radio-container input {
  display: none;
  /* 隐藏原始的输入框 */
}

.radio-container .radio-custom {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid #bbb;
  position: relative;
  top: -1px;
  display: inline-block;
  vertical-align: middle;
  transition: all 0.3s ease;
}

.radio-container .radio-custom:before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #bbb;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: all 0.3s ease;
}

/* 鼠标悬停时单选框样式 */
.radio-container:hover .radio-custom {
  border-color: #888;
}

/* 选中状态的单选框样式 */
.radio-container input:checked + .radio-custom:before {
  opacity: 1;
}
js
complete = (data) => {
  this.props.complete(data); // 调用父组件传递的回调函数,并传递数据
};

8.js 中一个 10-100 的随机数

js
const randomNumber = Math.floor(Math.random() * 91) + 10;

Math.random() 函数生成一个范围在 0 到 1 之间的随机小数(包括 0 不包括 1,左闭右开)。我们将其乘以 91,以获得一个范围在 0 到 91 之间的随机数。然后,我们使用 Math.floor() 函数向下取整,以确保结果是一个整数。最后,我们将结果加上 10,以将范围调整为 10 到 100。

9.gameType === 2 || 3 || 4 不正确

必须要这样写才可以:

js
gameType === 2 || gameType === 3 || gameType === 4;

10.css 将整个屏幕的高度固定为三个部分,并且每个部分有特定的高度

scss
.header-wapper {
  width: 100%;
  height: 5vh;
  box-sizing: border-box;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  background-color: #646cff;
}
.main-wapper {
  width: 100%;
  height: 90vh;
  display: flex;
  justify-content: center;
  align-items: center;
  //中间的左
  .main-left {
    width: 12%;
    height: 100%;
  }
  //中间的右
  .main-right {
    width: 88%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    //右面的body 体
    .body-wapper {
      width: 70vw;
      /* border: 1px #e8604c solid; */
      min-height: 80vh;
      background-color: #ffffff;
      padding: 0 20px;
      border-radius: 30px;
    }
  }
}
.footer-wapper {
  width: 100%;
  height: 5vh;
  display: flex;
  align-items: center;
  border-top: 2px dashed #646cff;
  box-sizing: border-box;
  background-color: #ffffff;
}

11.js 自定义 timeFormatter

js
export function timeFormatter(time) {
  let year = time.getFullYear();
  let month = time.getMonth() + 1;
  let day = time.getDate();
  if (month < 10) {
    month = "0" + month;
  }
  if (day < 10) {
    day = "0" + day;
  }
  return year + "-" + month + "-" + day;
}

12.react 中子到父传参的策略

父组件为 Staging.jsx:使用了 List 子组件

将函数通过 props 传递给子组件:

jsx
<List edit={this.editOneThing}></List>
js
editOneThing = (data) => {
  this.setState({
    editData: data,
    showDialogEdit: true,
  });
};

子组件:绑定给真实事件一个函数,函数中调用 props 传过来的函数

jsx
<div className='edit' onClick={() => this.edit(e)}>
  编辑
</div>
js
edit = (data) => {
  this.props.edit(data); // 调用父组件传递的回调函数,并传递数据
};

分析

react 的这种子到父的通讯非常方便,只需要通过 props 即可,而不需要用 自定义事件+emit

比 vue 和小程序都要方便!

13.react 的 props 快捷赋值给 dom/组件

父:

jsx
<div className='nav-wapper'>
  <MyNavLink to='/staging'>工作台</MyNavLink>
  <MyNavLink to='/analysis'>数据分析</MyNavLink>
</div>

子:

jsx
<NavLink
  activeClassName='add'
  className='list-group-item'
  {...this.props}></NavLink>