0%

React入门篇

前端热门技术栈有很多,其中遵循/类似MVVM或MVC设计模式的前端框架/Library有:React、Vue以及Angular等等。今天,我们首先谈一谈React的基本概念。

React 入门

一、如果ReactJS在HTML中

如果React的代码要写在HTML中,则需要放在属性typetext/babel<script>标签中。因为React使用的是JSX语法,与JS不兼容,需要被转化为JS语法才能显示在Web页面上。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<script src="../build/react.js"></script>
<script src="../build/react-dom.js"></script>
<script src="../build/browser.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// ** JSX code **
</script>
</body>
</html>

此外,有三个必须的库需要首先加载。react.jsReact的核心库react-dom.js提供与DOM相关的功能,例如将元素插入DOM节点。Browser.js是将JSX语法转换为JS语法,这一步很耗时,实际项目中会在服务端完成它。

二、ReactDOM.render()

它是React中最基础的方法,用于将JSX代码转换为HTML代码,并将其插入到指定的DOM节点。示例代码如下:

1
2
3
4
ReactDOM.render(
<div>...</div>,
document.getElementById('root')
);

三、JSX语法

就像上面代码演示的那样,HTML代码和JS代码并存在同一代码中,这就是JSX语法。它允许JS与HTML混写。其原理在于JSX语法:当遇到HTML标签(即<>)时会自动识别HTML,并按HTML规则解析;当遇到JS代码块(即{})时会自动识别JS,并按JS规则解析。

具体syntax语法学习,请参考官方文档。

四、组件

React允许将代码块封装成组件 component,然后像插入HTML标签一样,将其插入到DOM节点。示例代码如下:

1
2
3
4
5
6
7
8
9
10
var HelloMsg = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});

ReactDOM.render(
<HelloMsg name="Word!" />,
document.getElementById('root')
);

五、如何获取真实DOM节点

尽管操作组件类似于操作HTML标签,但是组件并非真实的DOM节点,而是存在于内存中的一种数据结构,称为虚拟DOM即 Virtual DOM。因此,只有在它被插入到文档/Document之后,才能生效成为真实的DOM。

这主要是因为React设计的DOM diffing算法,大致思想为:所有的DOM操作,会先在虚拟DOM上执行,然后再通过比对虚拟DOM和真实DOM,将真正发生改变的部分在真实DOM中更新。这样的做法大大地提高了网页的性能。

但是,有时我们也需要在组件中获取真实DOM,React给我们提供了**ref属性**。例如:在类组件中,可以调用this.refs.[refName]来获取真实的DOM节点。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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('root')
);

六、State——组件状态机

组件是有状态的,React的一大创新就是:将组件看成一个状态机,一开始有一个初始状态,然后通过与用户的交互,导致状态更新,进而触发组件重新渲染。这就实现了由状态驱动的理念单向数据流的特点即数据只能在状态中改变然后影响组件其它部分。

表单数据也是属于用户与组件的交互,因此也需要借助状态来读取和更新。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);

注:在React中,只有state/状态数据是可以改变的,而其它的如props/属性是不可变的。

七、类组件的生命周期

组件生命周期主要可以分为三个状态:

  • Mounting/挂载:已插入真实DOM
  • Updating/更新:正在被重新渲染
  • Unmounting/卸载:已移除真实DOM

并且React为每个状态提供了两种处理函数,**will函数(在进入状态前调用)和did函数(在进入状态后调用)**。主要使用的5个处理函数如下:

  • componentWillMount()
  • componentDidMount()
  • componentWillUpdate(object nextProps, object nextState)
  • componentDidUpdate(object prevProps, object prevState)
  • componentWillUnmount()

同时React还提供了一些特殊的状态的处理函数,例如shouldComponentUpdate(object nextProps, object nextState)在组件判断是否重新渲染时调用。

注:由于React官方正在逐步废弃Class组件,很多的处理函数已经不被官方推荐使用,因此,我们不多赘述Class组件。随着React官方对Hook的重视,我们在接下来的文章会重点介绍Hook的概念和使用。

一些不常用的功能

PropTypes

尽管组件可以接受任意类型的值来作为它的属性,但是有时,我们需要组件只接受特定的类型作为它的属性PropTypes可以帮助我们验证组件实例的属性是否符合要求。

具体用法如下:

1
2
3
4
5
6
7
8
9
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired, // title属性是必须的,且需为字符串
},

render: function() {
return <h1> {this.props.title} </h1>;
}
});

此外,getDefaultProps方法可以用来设置组件属性的默认值。具体用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var MyTitle = React.createClass({
getDefaultProps : function () {
return {
title : 'Hello World' // 设置属性title的默认值为Hello World
};
},

render: function() {
return <h1> {this.props.title} </h1>;
}
});

ReactDOM.render(
<MyTitle />,
document.body
);