1.react 实现 v-if 类似的功能
function MyComponent({ condition }) {
return (
<div>
{condition ? <div>条件为真时的内容</div> : <div>条件为假时的内容</div>}
</div>
);
}
或者
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 这个钩子里面进行
//要获取更新后的 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,
},
});
}
}
componentDidUpdate(prevProps) {
if (prevProps.allData !== this.props.allData) {
this.setState({ allData: this.props.initialValue });
// console.log(this.state.allData);
}
}
失败的情况(动态更新的 props 失败的情况)
如果不是动态的 props,那么是可以的:——> 静态可行
componentDidMount() {
// 最新的 props 指的是更新流程下的,更新不会调用这个钩子(只有在第一次挂载时调用)
// 所以在这里获取不到 最新的props
console.log(this.props);
}
如果不是动态的 props,那么是可以的:——> 静态可行
//在构造器里面赋值的话,props 不是最新的,跟componentDidMount的原理一样
constructor(props) {
super(props);
console.log(props);
this.state = {
data: {
time: props.data.time,
title: props.data.title,
notes: props.data.notes,
},
};
}
这个任何时候都不行:
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 里面进行使用即可:
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 钩子里面一定要有终止条件
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.合并对象:覆盖效果
//Object.assign合并两个对象,后面的会把前面已有的覆盖,没有的就添加到前面!
const newItem = Object.assign(this.state.editData, data);
//...合并对象和Object.assign是一样的,同样后面的会把前面已有的覆盖
const newItem = Object.assign(this.state.editData, data);
5.map 更改对象数组
更改对象数组中的某一整项:
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;
// }
// });
要修改对象数组中满足条件的一项的某个属性值:
const updatedArray = originalArray.map((item) => {
if (item.id === targetId) {
return { ...item, propertyToModify: newValue };
}
return item;
});
6.state 的属性是一个对象时的更新赋值策略
需要把整个对象一起赋值,不能单独赋值某一个属性
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 否则就变成和其他的是一组的了,就只能有一个被选中
<input type="radio" checked={this.state.isAllChecked} readOnly onChange={() =>
this.complete(e.id)}/>
checked 属性是控制是否被选中的状态的
对应的 css 伪类状态为 input:checked
自己构建自定义样式的 radio 的策略
注意:这里不在 radio 上使用 onChange 事件,而是在 span 上使用 onClick 事件
<div className='radio-container'>
{/* 一定不要给 radio 加 name 否则就变成大家是一组的了,就只能有一个被选中 */}
<input type='radio' checked={e.isDid} readOnly />
<span className='radio-custom' onClick={() => this.complete(e.id)}></span>
</div>
/* 自定义单选框样式 */
.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;
}
complete = (data) => {
this.props.complete(data); // 调用父组件传递的回调函数,并传递数据
};
8.js 中一个 10-100 的随机数
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 不正确
必须要这样写才可以:
gameType === 2 || gameType === 3 || gameType === 4;
10.css 将整个屏幕的高度固定为三个部分,并且每个部分有特定的高度
.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
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 传递给子组件:
<List edit={this.editOneThing}></List>
editOneThing = (data) => {
this.setState({
editData: data,
showDialogEdit: true,
});
};
子组件:绑定给真实事件一个函数,函数中调用 props 传过来的函数
<div className='edit' onClick={() => this.edit(e)}>
编辑
</div>
edit = (data) => {
this.props.edit(data); // 调用父组件传递的回调函数,并传递数据
};
分析
react 的这种子到父的通讯非常方便,只需要通过 props 即可,而不需要用 自定义事件+emit
比 vue 和小程序都要方便!
13.react 的 props 快捷赋值给 dom/组件
父:
<div className='nav-wapper'>
<MyNavLink to='/staging'>工作台</MyNavLink>
<MyNavLink to='/analysis'>数据分析</MyNavLink>
</div>
子:
<NavLink
activeClassName='add'
className='list-group-item'
{...this.props}></NavLink>