创建 React App
npx create-react-app my-app
cd my-app
npm start
JSX 语法
JSX 语法里面,有两种类型的标签
- 普通的 html 标签
<div></div>
<p></p>
<span></span>
- 组件标签
<App />
组件标签首字母必须大写
JSX 使用时最外层只能有一个标签
// index.js
ReactDom.render(<div><App /><Test /></div>, document.getElementById('root'));
// App.js
class App extends Component {
render() {
return (
<div>
<input />
<ul>
<li>learn React</li>
<li>learn Vue</li>
</ul>
</div>
);
}
}
有时代码结构要求不能在最外层添加div,这时可以用占位符标签 Fragment
// App.js
import React, { Component, Fragment } from 'react';
class App extends Component {
render() {
return (
<Fragment>
<input />
<ul>
<li>learn React</li>
<li>learn Vue</li>
</ul>
</Fragment>
);
}
}
数据绑定
React 是由数据驱动的,所以不要以 DOM 为关注点
// TodoList.js
import React, { Component, Fragment } from 'react';
class TodoList extends Component {
constructor(props) { // 固定形式
super(props); // 固定形式
this.handleInputChange = this.handleInputChange.bind(this); // 调用方法的 this 为 undefined 所以需要用 bind 来指定 this 指向类
this.handleKeyUp = this.handleKeyUp.bind(this);
this.state = { // 数据规定写在 state 里面
inputValue: '',
list: []
}
}
handleKeyUp(e) {
if (e.keyCode === 13 && e.target.value !== '') {
const list = [...this.state.list, this.state.inputValue];
this.setState({ list, inputValue: '' });
}
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value
});
}
handleItemDel(index) {
const list = [...this.state.list];
list.splice(index, 1);
this.setState({ list });
}
getListItem() {
return this.state.list.map((value, index) => {
return <li key={index} onClick={this.handleItemDel.bind(this, index)}>{value}</li>;
})
}
render() {
return (
<Fragment> // 仅占位,不在页面中显示
<input value= {this.state.inputValue} onChange={this.handleInputChange} onKeyUp={this.handleKeyUp}/>
<ul>
{ this.getListItem() }
</ul>
</Fragment>
);
}
}
export default TodoList;
JSX 语法细节
- JSX 语法在用到 class 时,需要改成 className,因为要避免和类的 class 相混淆
- JSX 语法在用到 label 的 for 时,要用 htmlFor
<label htmlFor="myinput"></label><input id="myinput" />
- JSX语法中添加注释,要加 {}
{/* 这是一个 JSX 语法中的注释 */}
- input 中的输入,不经转义直接输出
例如 <h1></h1> 直接显示为大字体的格式,这时
应该用 dangerouslySetInnerHTML 属性
...
getListItem() {
return this.state.list.map((value, index) => {
return <li key={index} onClick={this.handleItemDel.bind(this, index)} dangerouslySetInnerHTML={{__html: value}}></li>;
})
}
...
组件之间的传值
父组件通过属性的形式向子组件传值
// 父组件中通过属性向子组件传值
<TodoItem content={value} />
// 子组件中通过 this.props 接收父组件传过来的值
render() {
return <li>{this.props.content}</li>
}
render 函数执行时间
- 当组件初次创建的时候,render 函数会被执行一次
- 当 state 数据发生变更的时候,render 函数会被重新执行
- 当 props 数据发生变更的时候,render函数会被重新执行
ref 的使用
- ref 写在 html 标签上,获取的是 dom 节点
- ref 写在组件标签上,获取的是组件的 js 实例
<button ref={(button) => { this.buttonElem = button } }></button> // 获取元素绑定到实例上
setState 异步造成的一些问题
如果希望改变完数据之后才执行可以用一下写法
this.setState(() => {
return {
counter: newCounter
}
}, () => {
// 改变完数据之后执行的代码
});
生命周期函数
在 React 中,生命周期函数指的是组件在某一时刻会自动执行的函数
render() 就是生命周期函数
shouldComponentUpdate() 需要返回值,默认为 true ,如果为 true 则接下来的生命周期函数执行,如果为 false,则接下来的生命周期函数不执行
ajax 请求应放在 componentDidMount() 生命周期函数中
Ant Design
是 React 的一个组件库,具体使用方法见官网
路由
安装
npm install react-router-dom --save
使用
import React, { Component } from 'react';
import ReactDom from 'react-dom';
import { BrowserRouter, Route } from 'react-router-dom'; // 引入
import Antd from './Antd';
import Father from './Father';
import "antd/dist/antd.css";
class Entry extends Component {
render() {
return (
// 使用
<BrowserRouter>
<div>
<Route path="/antd" component={Antd}></Route>
<Route path="/father" component={Father}></Route>
</div>
</BrowserRouter>
);
}
}
ReactDom.render(<Entry />, document.getElementById('root'))
路由跳转
import React, { Component } from 'react';
import { Button } from 'antd';
import { Link } from 'react-router-dom'; // 引入 Link
class Antd extends Component {
render() {
return (
<Link to="/father"> // 跳转
<Button type="primary" style={{marginLeft: 20}}>按钮</Button>
</Link>
);
}
}
export default Antd;
路由携带参数
// 跳转时携带参数
<Link to="/father?a=123">
<Button type="primary" style={{marginLeft: 20}}>按钮</Button>
</Link
// 获取
console.log(this.props.location.search); // ?a=123
// 路由配置
<BrowserRouter>
<div>
<Route path="/antd" component={Antd}></Route>
<Route path="/list/:id" component={newList}></Route>
</div>
</BrowserRouter>
// 跳转时携带的参数
<Link to="/father/123">
<Button type="primary" style={{marginLeft: 20}}>按钮</Button>
</Link
// 获取
console.log(this.props.match.params.id);