1.在 React 组件的哪个生命周期函数中发起 AJAX 请求?
在componentDidMount
这个生命周期函数中发起 AJAX 请求。这样做你可以拿到 AJAX 请求返回的数据并通过 setState 来更新组件。
2.怎样才能在 JSX 中编写注释?
<div>
{/* 注释写在这里 */}
Hello, {name}!
</div>
<div>
{/* 多行注释
也同样有效。 */}
Hello, {name}!
</div>
3.如何将事件处理器(比如 onClick)传递给组件?
可以将事件处理器和其他函数作为 props 传递给子组件:
<button onClick={this.handleClick}>
4.如何为函数绑定组件实例?
在构造函数中绑定(ES2015) 推荐!
class Foo extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick}>Click Me</button>;
}
}
在 Render 中的绑定
class Foo extends Component {
handleClick() {
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick.bind(this)}>Click Me</button>;
}
}
注意:
在 render 方法中使用 Function.prototype.bind 会在每次组件渲染时创建一个新的函数,可能会影响性能
在 Render 中使用箭头函数
class Foo extends Component {
handleClick() {
console.log('Click happened');
}
render() {
return <button onClick={() => this.handleClick()}>Click Me</button>;
}
}
注意:
在 render 方法中使用箭头函数也会在每次组件渲染时创建一个新的函数,这会破坏基于恒等比较的性能优化。
5.可以在 render 方法中使用箭头函数吗?
一般来说是可以的,并且使用箭头函数是向回调函数传递参数的最简单的办法。但是如果遇到了性能问题,一定要进行优化!
6.为什么我的函数每次组件渲染时都会被调用?
确保你在传递一个函数给组件时,没有调用这个函数:
render() {
// Wrong: handleClick is called instead of passed as a reference!
return <button onClick={this.handleClick()}>Click Me</button>
}
正确做法是,传递函数本身(不带括号):
render() {
// Correct: handleClick is passed as a reference!
return <button onClick={this.handleClick}>Click Me</button>
}
7.如何传递参数给事件处理器或回调?
可以使用箭头函数包裹事件处理器,并传递参数:
<button onClick={() => this.handleClick(id)} />
以上代码和调用 .bind 是等价的:
<button onClick={this.handleClick.bind(this, id)} />
8.setState 实际做了什么?
setState() 会对一个组件的 state 对象安排一次更新。当 state 改变了,该组件就会重新渲染。
9.state 和 props 之间的区别是什么?
props(“properties” 的缩写)和 state 都是普通的 JavaScript 对象。它们都是用来保存信息的,这些信息可以控制组件的渲染输出,而它们的一个重要的不同点就是:props 是传递给组件的(类似于函数的形参),而 state 是在组件内被组件自己管理的(类似于在一个函数内声明的变量)。
10.为什么 setState 给了我一个错误的值?
在 React 中,this.props 和 this.state 都代表着已经被渲染了的值,即当前屏幕上显示的值。
调用 setState 其实是异步的 —— 不要指望在调用 setState 之后,this.state 会立即映射为新的值。如果你需要基于当前的 state 来计算出新的值,那你应该传递一个函数,而不是一个对象。
代码不会像预期那样运行的示例:
incrementCount() {
// 注意:这样 *不会* 像预期的那样工作。
this.setState({count: this.state.count + 1});
}
handleSomething() {
// 假设 `this.state.count` 从 0 开始。
this.incrementCount();
this.incrementCount();
this.incrementCount();
// 当 React 重新渲染该组件时,`this.state.count` 会变为 1,而不是你期望的 3。
// 这是因为上面的 `incrementCount()` 函数是从 `this.state.count` 中读取数据的,
// 但是 React 不会更新 `this.state.count`,直到该组件被重新渲染。
// 所以最终 `incrementCount()` 每次读取 `this.state.count` 的值都是 0,并将它设为 1。
}
11.应该如何更新那些依赖于当前的 state 的 state 呢?
给 setState 传递一个函数,而不是一个对象,就可以确保每次的调用都是使用最新版的 state。
12.给 setState 传递一个对象与传递一个函数的区别是什么?
传递一个函数可以让你在函数内访问到当前的 state 的值。因为 setState 的调用是分批的,所以你可以链式地进行更新,并确保它们是一个建立在另一个之上的,这样才不会发生冲突:
incrementCount() {
this.setState((state) => {
// 重要:在更新的时候读取 `state`,而不是 `this.state`。
return {count: state.count + 1}
});
}
handleSomething() {
// 假设 `this.state.count` 从 0 开始。
this.incrementCount();
this.incrementCount();
this.incrementCount();
// 如果你现在在这里读取 `this.state.count`,它还是会为 0。
// 但是,当 React 重新渲染该组件时,它会变为 3。
}
13.setState 什么时候是异步的?
目前,在事件处理函数内部的 setState 是异步的。
14.如何为组件添加 CSS 的 class?
传递一个字符串作为 className 属性:
render() {
return <span className="menu navigation-menu">Menu</span>
}
CSS 的 class 依赖组件的 props 或 state 的情况很常见:
render() {
let className = 'menu';
if (this.props.isActive) {
className += ' menu-active';
}
return <span className={className}>Menu</span>
}
15.可以使用行内样式吗?
可以,但是推荐使用class