你能够放心地在 JSX 当中使用用户输入,React DOM 在渲染以前默认会 过滤 全部传入的值。它能够确保你的应用不会被注入攻击。全部的内容在渲染以前都被转换成了字符串。这样能够有效地防止 XSS(跨站脚本) 攻击。html
Babel 转译器会把 JSX 转换成一个名为 React.createElement() 的方法调用。react
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
复制代码
等价es6
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
复制代码
React.createElement() 这个方法首先会进行一些避免bug的检查,以后会返回一个相似下面例子的对象:数组
// 注意: 如下示例是简化过的(不表明在 React 源码中是这样)
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world'
}
};
复制代码
这样的对象被称为 “React 元素”。它表明全部你在屏幕上看到的东西。React 经过读取这些对象来构建 DOM 并保持数据内容一致。浏览器
与浏览器的 DOM 元素不一样,React 当中的元素事实上是普通的对象,(也就是html标签+内容)React DOM 能够确保 浏览器 DOM 的数据内容与 React 元素保持一致。bash
const element = <h1>hello</h1>;
复制代码
要将React元素渲染到根DOM节点中,咱们经过把它们都传递给 ReactDOM.render() 的方法来将其渲染到页面上:dom
const element = <h1>hello</h1>;
ReactDOM.render(element,document.getElementById('root'));
复制代码
React 元素都是不可变的。当元素被建立以后,你是没法改变其内容或属性的.一个元素就好像是动画里的一帧,它表明应用界面在某一时间点的样子。异步
组件能够将UI切分红一些独立的、可复用的部件,这样你就只需专一于构建每个单独的部件。函数
组件从概念上看就像是函数,它能够接收任意的输入值(称之为“props”),并返回一个须要在页面上展现的React元素。动画
函数
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
复制代码
es6类继承
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
复制代码
React元素也能够是用户自定义的组件: 例如,这段代码会在页面上渲染出”Hello,Sara”:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
复制代码
过程:一、咱们对<Welcome name="Sara" ,/>元素调用了ReactDOM.render()方法。
二、React将{name: 'Sara'}做为props传入并调用Welcome组件。
三、Welcome组件将<h1,>Hello, Sara</h1,>元素做为结果返回。
四、React DOM将DOM更新为<h1,>Hello, Sara</h1,>。
组件名称必须以大写字母开头。
例如,<div,> 表示一个DOM标签,但 <Welcome,> 表示一个组件,而且在使用该组件时你必须定义或引入它。
组件的返回值只能有一个根元素。这也是咱们要用一个<div,>来包裹全部<Welcome ,/>元素的缘由。
定义为类的组件有一些额外的特性。局部状态就是如此:只能用于类的一个功能。
状态与属性十分类似,可是状态是私有的,彻底受控于当前组件。
你能够经过5个步骤将函数组件 Clock 转换为类
一、建立一个名称扩展为 React.Component 的ES6 类
二、建立一个叫作render()的空方法
三、将函数体移动到 render() 方法中
四、在 render() 方法中,使用 this.props 替换 props
五、删除剩余的空函数声明
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
复制代码
Clock 如今被定义为一个类而不仅是一个函数
使用类就容许咱们使用其它特性,例如局部状态、生命周期钩子
咱们会通过3个步骤将 date 从属性移动到状态中:
一、在 render() 方法中使用 this.state.date 替代 this.props.date
2.添加一个类构造函数来初始化状态 this.state
3.从 元素移除 date 属性: 代码以下
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
复制代码
咱们能够在组件类上声明特殊的方法,当组件挂载或卸载时,来运行一些代码:
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
} //当组件输出到 DOM 后会执行 componentDidMount() 钩子,
//这是一个创建定时器的好地方:
componentWillUnmount() {
clearInterval(this.timerID);
} //咱们将在 componentWillUnmount()生命周期钩子中卸载计时器:
复制代码
最后,咱们实现了每秒钟执行的 tick() 方法。
它将使用 this.setState() 来更新组件局部状态:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
!!!!
tick() {
this.setState({
date: new Date()
});
}//setState() 来调度UI更新。
//经过调用 setState() ,React 知道状态已经改变,
//并再次调用 render() 方法来肯定屏幕上应当显示什么。
!!!!
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
复制代码
让咱们快速回顾一下发生了什么以及调用方法的顺序:
一、当 被传递给 ReactDOM.render() 时,React 调用 Clock 组件的构造函数。 因为 Clock 须要显示当前时间,因此使用包含当前时间的对象来初始化 this.state 。 咱们稍后会更新此状态。
2.React 而后调用 Clock 组件的 render() 方法。这是 React 了解屏幕上应该显示什么内容,而后 React 更新 DOM 以匹配 Clock 的渲染输出。
3.当 Clock 的输出插入到 DOM 中时,React 调用 componentDidMount() 生命周期钩子。 在其中,Clock 组件要求浏览器设置一个定时器,每秒钟调用一次 tick()。
4.浏览器每秒钟调用 tick() 方法。 在其中,Clock 组件经过使用包含当前时间的对象调用 setState() 来调度UI更新。 经过调用 setState() ,React 知道状态已经改变,并再次调用 render() 方法来肯定屏幕上应当显示什么。 这一次,render() 方法中的 this.state.date 将不一样,因此渲染输出将包含更新的时间,并相应地更新DOM。
5.一旦Clock组件被从DOM中移除,React会调用componentWillUnmount()这个钩子函数,定时器也就会被清除。
关于 setState() 这里有三件事情须要知道
1.不要直接更新状态
// Wrong 错误!!
this.state.comment = 'Hello';
应当使用 setState():
// Correct
this.setState({comment: 'Hello'});
复制代码
构造函数是惟一可以初始化this.state的地方。
2.状态更新多是异步的
由于 this.props 和 this.state 多是异步更新的,你不该该依靠它们的值来计算下一个状态。
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
复制代码
要修复它,请使用第二种形式的 setState() 来接受一个函数而不是一个对象。 该函数将接收先前的状态做为第一个参数, 将这次更新被应用时的props作为第二个参数:
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
复制代码
三、状态更新合并
父组件或子组件都不能知道某个组件是有状态仍是无状态,而且它们不该该关心某组件是被定义为一个函数仍是一个类。
这就是为何状态一般被称为局部或封装。 除了拥有并设置它的组件外,其它组件不可访问。
react和dom的很类似,可是有一些语法的不一样
React事件绑定属性的命名采用驼峰式写法,而不是小写。
若是采用 JSX 的语法你须要传入一个函数做为事件处理函数,而不是一个字符串(DOM元素的写法) eg::: 传统的 HTML:
<button onclick="activateLasers()">
Activate Lasers
</button>
复制代码
React 中稍稍有点不一样:
<button onClick={activateLasers}>
Activate Lasers
</button>
复制代码
使用 React 的时候你不须要使用 addEventListener 为一个已建立的 DOM元素添加监听器。你仅仅须要在这个元素初始渲染的时候提供一个监听器。
使用”受控组件”,每一个状态的改变都有一个与之相关的处理函数。这样就能够直接修改或验证用户输入。例如,咱们若是想限制输入所有是大写字母,咱们能够将handleChange 写为以下:
handleChange(event) {
this.setState({value: event.target.value.toUpperCase()});
}
复制代码
在React中,<textarea,>会用value属性来代替。这样的话,表单中的<textarea,> 很是相似于使用单行输入的表单:
class EssayForm extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 'Please write an essay about your favorite DOM element.'
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('An essay was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<textarea value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
复制代码
注意this.state.value是在构造函数中初始化,这样文本区域就能获取到其中的文本。
请注意,Coconut选项最初因为selected属性是被选中的。在React中,并不使用以前的selected属性,而在根select标签上用value属性来表示选中项。这在受控组件中更为方便,由于你只须要在一个地方来更新组件。例如:
构造函数中
this.state = {value: 'coconut'};
类中
handleChange(event) {
this.setState({value: event.target.value});
}
render return中
<select value={this.state.value} onChange={this.handleChange}>
复制代码