key
key 可以帮助 React 识别哪些元素改变了,比如被添加或删除。数组中的每一个元素都需要设定key值,否则会报错。
NumberList组件接收 numbers 数组作为参数并输出一个元素列表。
const numbers = [1, 2, 3, 4, 5];
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li>{number}</li>); // × 没加key会报错
<li key={number.toString()}>//在 map() 方法中的元素需要设置 key 属性。
return (
<ul>{listItems}</ul> );
}
ReactDOM.render(
<NumberList numbers={numbers} />, document.getElementById('root')
);
数组元素中使用的 key 在其兄弟节点之间应该是独一无二的。然而,它们不需要是全局唯一的。当生成两个不同的数组时,可以使用相同的 key 值
key 会传递信息给 React ,但不会传递给组件。如果组件中需要使用 key 属性的值,请用其他属性名显式传递这个值:
const content = posts.map((post) =>
<Post
key={post.id} id={post.id} title={post.title} />
);
上面例子中,Post 组件可以读出 props.id,但是不能读出 props.key。
表单受控组件
表单受控组件:
由React控制表单输入内容和用户输入过程的组件。
- 设置value值,value由state控制
- value值一般在onChange事件中通过setState进行修改 表单非受控组件:
表单由 DOM 处理的组件
- 不设置value值
- 通过ref获取dom节点然后再取value值
Refs&DOM
从组件获取真实 DOM 的节点
var MyComponent = React.createClass({
handleClick: function() {
this.refs.myTextInput.focus();
},
render: function() {
return (
<div>
<input type="text" ref="myTextInput" />
<input type="button" value="Focus the text input" onClick={this.handleClick} />
</div>
);
}
});
ReactDOM.render(
<MyComponent />,
document.getElementById('example')
);
上面代码中,组件 MyComponent 的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref 属性,然后 this.refs.[refName] 就会返回这个真实的 DOM 节点。
需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件之后,才会读取 this.refs.[refName] 属性。
表单非受控组件
用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props读取
var Input = React.createClass({
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function () {
var value = this.state.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div>
);
}
});
ReactDOM.render(<Input/>, document.body);
上面代码中,文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种情况
Router
react-router 是官方指定和维护的 React 路由库,它通过管理 URL,实现组件间切换和状态 (state) 的变化。Router组件本身只是一个容器,真正的路由要通过Route组件定义。
传统开发中的路由,是由服务端根据不同的用户请求地址 URL,返回不同内容的页面,而前端路由则将这些任务通过 JS 在浏览器端完成,SPA 应用(单页面应用) 则是前端路由的最佳适用场景,因为它结构简单,只需更新页面部分显示内容 也不必每次都从服务端获取内容。
基本用法
// 使用 ES6 的转译器,如 babel
import { Router, Route, Link } from 'react-router'
// 不使用 ES6 的转译器
var ReactRouter = require('react-router')
var Router = ReactRouter.Router
var Route = ReactRouter.Route
var Link = ReactRouter.Link
Router 组件
react-router 的工作方式,是在组件树顶层放一个 Router 组件,然后在组件树中散落着很多 Route 组件,顶层的 Router 组件负责分析监听 URL 的变化,在它之下的 Route 组件可以直接读取这些信息。
Router 是“提供者”,Route是“消费者”。
BrowserRouter:使用于现代浏览器,支持H5 history
APIHashRouter:常用于旧款浏览器。
MemoryHistory:常用于非DOM环境,例如React Native或者测试,History存于内存。
BrowserRouter 方式的路由:
https://xxx.com/a
https://xxx.com/b
HashRouter 方式的路由:
https://xxx.com/#/a
https://xxx.com/#/b
createMemoryHistory
主要用于服务器渲染。它创建一个内存中的history对象,不与浏览器URL互动
引入方式:
import {Route, BrowserRouter as Router} from "react-router-dom";
对于浏览器项目通常选用: <BrowserRouter> 和 <HashRouter> 组件来实现 Router
react-native 项目通常选用:<MemoryHistory>
Route 组件
Route只是一个具有渲染方法的普通 React 组件,路由匹配成功则渲染该组件。
三个常用属性:
path:路由的匹配规则(可以省略)path可以表示相对路径,也可以表示绝对路径,一般多采用绝对路径.
exact:用于精确匹配路由(可以省略)
component:需要渲染的组件
一个完整的路由:
import {Route, BrowserRouter as Router} from "react-router-dom";
import A from 'A'
import B from 'B'
const routing = (
<Router>
<Route component={Home} >
<Route exact path="/a" component={A} />
<Route exact path="/b" component={B} />
</Router>
)
ReactDOM.render(routing, document.getElementById("root"));
路由跳转
Link组件 生成一个链接,允许用户点击后跳转到另一个路由
import React, {Component} from "react";
import {Link} from 'react-router';
class App extends Component {
render() {
return (
<div>
<h1>App</h1>
<ul>
<li><Link to="/about">About</Link></li>
<li><Link to="/inbox">Inbox</Link></li>
</ul>
{this.props.children}
</div>
)
}
}
Link组件用于正常的用户点击跳转,browserHistory.push则用来处理表单跳转、点击按钮跳转等操作。
class Inbox extends Component {
Logout(){
browserHistory.push('/'); //该方法可用于表单跳转和点击按钮跳转
}
render() {
return (
<div>
<h2>Inbox</h2>
{this.props.children || "Welcome to your Inbox"}
<ul>
<li><Link to="/">App</Link></li>
<li><Link to="/inbox/message">Message</Link></li>
</ul>
{this.props.children}
<button onClick={this.Logout.bind(this)}>退出</button>
</div>
)
}
}
参考文章:
react-guide.github.io/react-route…