列表
【keys】
keys可以在DOM中的某些元素被增加或删除的时候帮助React识别哪些元素发生了变化。因此应当给数组中的每一个元素赋予一个确定的标识。
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
一个元素的key最好是这个元素在列表中拥有的一个独一无二的字符串。通常,使用来自数据的id作为元素的key。当元素没有确定的id时,可以使用序列号索引index作为key。
const todoItems = todos.map((todo, index) =>
<li key={index}>
{todo.text}
</li>
);
[注意]如果列表可以重新排序,不建议使用索引来进行排序,因为这会导致渲染变得很慢。
JSX允许在大括号中嵌入任何表达式。
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
表单
【可控组件和不可控组件】
在React中的input标签
是有些小坑的,input
本身就有自己的缓存机制,然后React的state
也有缓存机制,像<input>
,<textarea>
, 和 <select>
这类表单元素会维持自身状态,并根据用户输入进行更新。但在React中,可变的状态通常保存在组件的状态属性中,并且只能用 setState() 方法进行更新。这两种缓存机制我们在编码中是要进行取舍的。将input
中的value
绑定到state
的React组件就是可控组件,反之则是不可控组件。
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
由于 value
属性是在表单元素上设置的,因此显示的值将始终为 React数据源上this.state.value
的值。由于每次按键都会触发 handleChange
来更新当前React的state
,所展示的值也会随着不同用户的输入而更新。
可控组件的优点:
符合React单向数据流特性,即从state
流向render
输出的结果,数据存储在state
中,便于访问和处理。
【textarea】
在HTML当中,<textarea>
元素通过子节点来定义它的文本内容。在React中,<textarea>
会用value
属性来代替,这样的话,表单中的<textarea>
非常类似于使用单行输入的表单:
<textarea value={this.state.value} onChange={this.handleChange} />
【select】
在React中,并不使用之前的selected
属性,而在根select标签
上用value
属性来表示选中项。这在受控组件中更为方便,因为只需要在一个地方来更新组件。
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
</select>
【多个input】
有处理多个受控的input元素时,可以通过给每个元素添加一个name
属性,来让处理函数根据 event.target.name
的值来选择做什么。
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}