介绍React开发环境的初始化,主要包括:组件定义、props属性、state状态、组件生命周期、事件处理

React环境初始化

入门介绍:

声明式:数据驱动

组件化:把相似的代码放到一起进行复用,传递数据

  • 官网:

英文:https://reactjs.org/

中文:https://doc.react-china.org/

方式一: 脚手架 (快捷、稳定)

  • 官方教程: 参考链接1 参考链接2
  • 执行命令:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    npm install -g create-react-app
    create-react-app my-app

    cd my-app
    npm start
    # 或使用以下命令 If you have npm 5.2.0+ installed, you may use npx instead.
    npx create-react-app my-app

    cd my-app
    npm start

方式二: Webpack (步骤较多按下不表)

元素渲染

元素是构成 React 应用的最小单位。

1
const element = <h1>Hello, world</h1>;

渲染元素

1
2
3
4
5
6
7
8
import React from 'react';
import ReactDOM from 'react-dom';

const element = <h1>Hello, world</h1>;
ReactDOM.render(
element,
document.getElementById('root')
);

React和ReactDOM为以下入口文件代码默认导包

组件及组件状态

组件可以将界面分割成一些的独立的、可复用的组成部分,我们只需专注于构建每一个单独的部分。按钮,对话框,列表,输入框都是组件。

组件从概念上看就像是函数,它可以接收任意的输入值(称之为“props”),并返回一个需要在页面上展示的React元素。

函数定义组件(无状态)

JavaScript函数

1
2
3
function Hello(props) {
return <h1>Hi, {props.name}</h1>;
}

类定义组件(有状态)

class由es6支持

1
2
3
4
5
class Hello extends React.Component {
render() {
return <h1>Hi, {this.props.name}</h1>;
}
}

以上两个组件效果在React中相同

注意: 组件名首字母必须大写

组合组件

组件之间可以相互引用, 通常把App组件作为根组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function App(props) {
return (
<div>
<div>
<h1>{props.team}</h1>
<p>成立时间: {props.date.toLocaleString()}</p>
<p>成员{props.count}</p>
</div>
<Hello name="悟空" />
<Hello name="三藏" />
<Hello name="八戒" />
<Hello name="沙僧" />
</div>
);
}

ReactDOM.render(
<App team="西天取经团" date={new Date()} count={4}/>,
document.getElementById('root')
);

可在Chrome安装React插件查看结构

注意:组件的返回值只能有一个根元素, 所以用一个div包裹所有Hello元素

Props 属性

props有两种输入方式:字符串“”大括号{}

props不可修改,属性只读, 强行修改会报错

State 状态

自动更新时钟

1
2
3
4
5
6
7
8
9
10
11
12
13
function tick() {
const element = (
<div>
<h1>时钟</h1>
<h2>current: {new Date().toLocaleString()}</h2>
</div>
)
ReactDOM.render(
element,
document.getElementById('root')
);
}
setInterval(tick, 1000);

应用一般只进行一次ReactDOM.render()渲染

  • 封装时钟
  • 函数->类 / 定义局部状态属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Clock extends React.Component {

constructor(props) {
super(props);
this.state = {
date: new Date(),
};
setInterval(() => {
this.tick()
}, 1000);
}
tick() {
// 更新date
this.setState({
date: new Date()
})
}
render() {
return (
<div>
<h1>Hi, clock Component state new!</h1>
<h2>current: {this.state.date.toLocaleString()}</h2>
</div>
);
}
}

ReactDOM.render(
<Clock />,
document.getElementById('root')
);
  1. state只能在构造函数初始化 this.state={...}
  2. 通过this.setState({...})更新并渲染组件
  3. 调用setState时, React会将新的state合并到当前的state中

组件生命周期

React中组件的生命周期

在componentDidMount初始化任务

在componentWillUnmount清理任务

事件处理

函数定义组件

1
2
3
4
5
6
7
8
function ActionButton() {
function handleClick(e) {
console.log('The Button was clicked.');
}
return (
<button onClick={handleClick}>按我</button>
);
}

类定义组件

  • 注意以下两种写法的区别
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class App extends React.Component {
handleClick(e){
console.log(this);
console.log("handleClick!");
}

render() {
return (
<div>
<div>
<button onClick={this.handleClick}>
按钮1 {'{this.handleClick}'}
</button>
</div>
<div>
<button onClick={() => this.handleClick()}>
按钮2 箭头函数 {"{() => this.handleClick()}"}
</button>
</div>
</div>
);
}
}

默认语法:类的方法默认不会绑定 this,也就是说在handleClick内部的this为undefined

箭头式语法:在每次App渲染时都会创建一个新的回调函数,可能会造成子组件的额外渲染

  • 默认语法this问题解决方案:事件绑定 / 属性初始化器语法:
  1. 构造函数绑定this

    1
    2
    3
    4
    constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    }
  2. 使用 属性初始化器 语法 声明handleClick

    1
    2
    3
    4
    5
    handleClick = () => {
    this.setState(preState => ({
    count: preState.count + 1
    }))
    }
  • 计数器游戏

注意事项:

  • 组件名首字母必须大写

  • 组件的返回值只能有一个根元素

  • props属性是只读的