一、React元素
React元素用来构建虚拟DOM(React DOM),与真实DOM有相同的树状结构,而真实DOM由DOMElement组成。
1、创建
React.createElement(
type, // 必传,要创建的HTML元素标签名的字符串('div','span')
[props],// 可传,元素的属性
[...children]// 可传,元素的下一层嵌套,通过React.createElement嵌套元素
)
// 示例
var child1 = React.createElement('li', null, 'one');
var child2 = React.createElement('li', null, 'two');
var content = React.createElement('ul', { className: 'teststyle' }, child1, child2); // 第三个参数可以分开也可以写成一个数组
ReactDOM.render(
content,
document.getElementById('example')
);
2、JSX
使用React.createElement创建元素会造多层嵌套,JSX使创建元素更简易。
JSX:JS的一种类XML的语法扩展,提供给预处理器使用,预处理器再将其转换成React.createElement。提供{}用于编写JavaScript表达式。
class CreateComment extends Component {
render() {
<input value={this.state.user} />
}
}
二、React组件
将React元素组织在一起,有助于将功能、标记、样式等进行封装,方便复用。
1、有状态的React组件(React类)
创建
通过声明一个继承自 React.Component 抽象基类的JavaScript类来代表一个组件,至少需要定义render 方法,在 render 方法里面返回需要渲染的元素。
render方法可以嵌套但最高层只有一个节点,可以访问持久化的组件状态、组件方法、继承React.Component 抽象基类的方法;
class Todo extends React.Component {
render() {
return <li>Hello, {this.props.content}</li>;
}
}
<Todo content="图雀" />
// 旧方式
import createReactClass from 'create-react-class';
const HelloWorld = createReactClass({
render() { return(<p>Hello, world!</p>) }
})
状态
- state:可变,在组件类定义,类实例通过this.state访问,
- props:不可变不可修改,来自父组件或组件自身的defaultProps静态方法,通过this.props访问,
state的初始化和更新
state在constructor方法中进行初始化;
class CreateComment extends Component {
constructor(props) {
super(props);
this.state = {
user: ""
};
}
render() {
<input value={this.state.user} />
}
}
React需要追踪状态并确保虚拟DOM和实际DOM同步,使用setState更新状态;调用setState更新时,无需立即执行,而是创建一个挂起的状态转换,React选择批量更新提高效率。
React实现了一个合成事件系统作为虚拟DOM的一部分,将浏览器事件转换为React事件,这些事件设置在React元素上。
setState(
updater,// 设置新状态 (prevState,props)=> stateChange
[callback]// 回调函数
)
// 实例
class CreateComment extends Component {
constructor(props) {
super(props);
this.state = {
user: ""
};
this.hanleUserChange =this.hanleUserChange.bind(this);
}
hanleUserChange(event){
const val = event.target.value;
this.setState({// 浅合并
user:val
})
}
render() {
<input value={this.state.user} onChange={this.handleUserChange}/>
}
}
props的验证器PropTypes
PropTypes验证器使React类组件具有验证属性数据类型和是否必传的功能,使用时需安装prop-types包,通过将类的静态属性或通过类定义后的简单属性赋值添加验证。
var title = 123;// 属性 title 是必须的且是字符串,非字符串类型会自动转换为字符串
class MyTitle extends React.Component {
static propTypes = {// 通过类的静态属性
title: PropTypes.string
};
render() {
return (
<h1>Hello, {this.props.title}</h1>
);
}
}
MyTitle.propTypes = {// 或通过类定义后的简单属性赋值(string为类型,isRequired为必传)
title: PropTypes.string.isRequired
};
ReactDOM.render(
<MyTitle title={title} />,
document.getElementById('example')
);
默认属性
通过为类定义一个defaultProps静态属性添加默认属性
class MyTitle extends React.Component {
static defaultProps = {// 默认属性
title: '标题'
};
render() {
return (
<h1>Hello, {this.props.title}</h1>
);
}
}
ReactDOM.render(
<MyTitle />,
document.getElementById('example')
);
2、无状态的函数组件
创建
// 普通函数
function HelloMessage(props) {
return <h1>Hello {props.name}!</h1>;
}
// 箭头函数
const HelloMessage = (props) => {
return <h1>Hello {props.name}!</h1>;
}
<HelloMessage name="Runoob"/>;
- setState执行数据的浅合并,保留任何没有被覆盖的顶级属性;
- 单向数据流:属性从父组件流向子组件,子组件通过回调函数将数据回送给父组件,但不能直接修改父组件的状态,父组件也无法直接修改子组件状态。组件通过属性完成组件交互。
三、ReactDOM渲染元素
ReactDOM.render(
ReactElement element,// React元素
DOMElement container,// DOM元素,容器
)
<!--创建一个id为root的div元素,用于渲染容器-->
<div id="root"></div>
import React from "react";
import ReactDOM from "react-dom";// React渲染器,利用render方法渲染
import App from "./components/App";
ReactDOM.render(
<App>,
document.getElementById("root")
);