React中,推出了一种新的语法取名为JSX,它给了JS中写HTML标签的能力,不须要加引号。JSX的语法看起来是一种模板,然而它在编译之后,会转成JS语法,只是书写过程当中的语法糖。
JSX的解析器会帮咱们读取这种语法并加以处理。
下面是一个简单的例子。javascript
const element = <h1 className="greeting">Hello, world!</h1>;
其实至关于以下的代码:html
const element = React.createElement({ 'h1', {className: 'greeting'}, 'Hello, world!', 'Xxx' })
第一个参数是类型,能够是HTML标签,也能够是React组件;第二个参数是props对象;第三个之后参数是children,会按照传入顺序依次排列。
固然第三个参数也能够传入数组,若是第三个参数传入数组,则后面再传入其余子节点,就会报错。
JSX提供了一种HTML和JS混合编写的能力。在须要使用JS表达式的地方,用一组花括号包裹起来便可:java
function formatName(user) { return user.firstName + ' ' + user.lastName; } const user = { firstName: 'Harper', lastName: 'Perez' }; const element = ( <h1 className="test"> Hello, {formatName(user)}! </h1> ); ReactDOM.render( element, document.getElementById('app') );
因为class在js中关键字,因此使用className去替代。
上面说到了JSX实际上是语法糖,因此若是要循环嵌入列表,能够直接将列表传进来:react
const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li>{number}</li> ); ReactDOM.render( <ul>{listItems}</ul>, document.getElementById('app') );
在控制台中会看到这样的报错:es6
warning.js:33 Warning: Each child in an array or iterator should have a unique "key" prop.
这是因为react使用virtual dom来渲染真实节点,在列表渲染时,若是每一个item没有对应的key,react处理起增删改时就会很慢,因此,渲染列表时,最好给每个item增长一个惟一的key。数组
const listItems = numbers.map((number, index) => <li key={index}>{number}</li> );
React中最重要的概念就是组件。性能优化
Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.app
组件能够看作是一个函数,指定了输入(props),就会给出输出(一个React元素)。
建立组件有两种方法:
1.函数dom
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
2.es6的类函数
class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
第二种方法建立的组件,能够拥有内部状态(state)和生命周期函数。
若是只是展现信息,没有复杂的操做,能够选择第一种函数方法。若是组件比较复杂,而且须要在不一样的时期作初始化或者销毁等工做,就要采用第二种ES6类方法。
State相似于props,但它是组件私有的而且彻底由组件控制。
下面咱们结合一个Clock类来演示State的概念。
import React, {Component} from 'react'; export default class Clock extends Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
在这个组件里,Clock就拥有了本身的状态,而不是从外界发生传入。接下来咱们增长一个定时器的功能,来引入生命周期。
import React, {Component} from 'react'; export default class Clock extends Component { ... componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID) } tick () { this.setState({date: new Date()}) } ... }
注意:在React中,调用setState方法去修改state,会触发View视图层的修改,直接设置state就不会触发state的修改。
上面引入了两个生命周期方法:componentDidMount , componentWillUnmount 。
componentDidMount 会在组件挂载到DOM节点上以后触发,而 componentWillUnmount 会在组件从节点上移除之后触发。
React还有不少生命周期方法,下面作一个详细的说明。
在React中,一个组件可能会经历建立、挂载、更新、卸载、销毁这些事件,React为咱们提供了钩子函数来在这些事件触发时进行操做。
他的生命周期能够分为三大部分:
建立、更新、销毁。
建立组件并将其插入DOM时,下面的方法会依次触发
constructor() static getDerivedStateFromProps() render() componentDidMount()
更新时,将会触发
static getDerivedStateFromProps() shouldComponentUpdate() render() getSnapshotBeforeUpdate() componentDidUpdate()
卸载时,触发
componentWillUnmount()
为了更加直观的查看生命周期方法,能够参考这张图:
图片来源:http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/。
Render阶段,把一些state和props计算执行。
Commit阶段就是把React组件插入到真实DOM节点上,这个时候可使用DOM。
而Pre-commit阶段就是在插入真实DOM以前,这个阶段能够读取DOM。
1.用来初始化props和state。
2.是惟一能够直接修改state的地方。
1.当state须要从props初始化时使用
2.尽可能不要使用:由于维护二者的一致会增长复杂度
3.每次render前都会被调用
4.典型场景:表单控件获取默认值
不能缺乏的,它实际上决定了组件到底要渲染成什么样子。
1.在UI渲染完成以后触发
2.只执行一次
3.一般在这个方法里触发Ajax请求等操做。
有三种状况会触发update。
props发生了改变,setState执行,forceUpdate执行。
前两种很少说,第三个forceUpdate触发的场景比较少见,若是Render方法使用了props和state之外的数据,就须要这个方法。
这里是一个例子。
1.决定virtual dom是否会重绘
2.通常能够用pure component自动实现
3.这个方法用来作性能优化相关的操做。有的时候state和props的更新其实不会影响dom的展现,没有必要再次渲染DOM。
1.更新DOM前被触发,state已经更新
2.它能够将以前DOM的状态传递给componentDidUpdate,而后进行计算处理后更新DOM。
这里一个例子。
1.每次UI更新后都会调用
2.props或者state修改后都会触发
这个阶段只会触发一个方法。
1.只调用一次
2.能够在这个方法里清除计时器,关闭一些链接等。
以上是JSX、组件概念、props、state、生命周期的介绍。 感谢阅读。