组件是React的核心概念,是React应用程序的基石。组件将应用的UI拆分成独立的、可复用的模块,React应用程序正是由一个个组件搭建而成的。
定义一个组件有两种方法:
使用class定义组件需要满足的两个条件:
在使用class定义类组件后,需要使用export将类组件导出,以便在其他文件中使用。
在使用时,需要导入react-dom库,并使用ReactDOM.render()显示,该方法有两个参数:
使用class定义组件:
import React from 'react'
class PostList extends React.Component {
render() {
return (
帖子列表:
- 帖子1
- 帖子2
- 帖子3
- 帖子4
- 帖子5
- 帖子6
);
}
}
export default PostList;
使用:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import reportWebVitals from './reportWebVitals';
import PostList from './p2/PostList';
ReactDOM.render(
<React.StrictMode>
<PostList></PostList>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
组件的props属性用于把父组件中的数据或者方法传递给子组件,供子组件使用。
props属性是不可变的。
创建子组件:
import React from 'react'
class PostItem extends React.Component {
render() {
const {title, author, date} = this.props;
return(
{title}
创建人:{author}
创建时间:{date}
);
}
}
export default PostItem;
在父组件中使用:
import React from 'react'
import PostItem from './PostItem'
//声明数据
const data = [
{ title: "帖子1", author: "张三", date: "2021-02-15 11:11:11"},
{ title: "帖子2", author: "李四", date: "2021-02-15 12:11:11"},
{ title: "帖子3", author: "王五", date: "2021-02-15 13:11:11"},
{ title: "帖子4", author: "赵六", date: "2021-02-15 14:11:11"}
];
class PostList extends React.Component {
render() {
return (
帖子列表:
{
//循环显示
data.map(item =>
)}
);
}
}
export default PostList;
组件的state是组件内部的状态,state的变化最终将反映到组件UI的变化上。
可以在组件的构造方法(constructor)中通过this.state定义组件的初始状态,并通过this.setState方法改变组件的状态,进而组件的UI也会随之重新渲染。
注意点:
添加点击事件:
import React from 'react'
class PostItem extends React.Component {
constructor(props) {
super(props);
//定义初始状态
this.state = {
vote: 0
}
}
//定义点击事件
handleClick() {
let newVote = this.state.vote;
newVote++;
this.setState({
vote: newVote
});
}
render() {
const {title, author, date} = this.props;
return(
{title}
创建人:{author}
创建时间:{date}
{this.state.vote}
);
}
}
export default PostItem;
React组件正是由props和state两种类型的数据驱动渲染出组件UI。props是组件对外的接口,组件通过props接受外部传入的数据;state是组件对内的接口,组件内部状态的改变通过state来反映。props是只读的,不能从内部修改props;state是可变的,组件状态的变化通过修改state来实现。
更改之后的PostList:
import React from 'react'
import PostItem from './PostItem'
class PostList extends React.Component {
constructor(props) {
super(props);
//数据
this.state = {
posts:[]
};
//定时器
this.timer = null;
//指定点击事件
this.handleVote = this.handleVote.bind(this);
}
//初次渲染结束
componentDidMount() {
//异步模拟从服务端请求数据
this.timer = setTimeout(() => {
this.setState({
posts: [
{id: 1, title: "帖子1", author: "张三", date: "2021-02-15 11:11:11", vote: 0},
{id: 2, title: "帖子2", author: "李四", date: "2021-02-15 12:11:11", vote: 0},
{id: 3, title: "帖子3", author: "王五", date: "2021-02-15 13:11:11", vote: 0},
{id: 4, title: "帖子4", author: "赵六", date: "2021-02-15 14:11:11", vote: 0},
]});
}, 1000);
}
//组件卸载之前
componentWillUnmount() {
if(this.timer) {
//清除计时器
clearTimeout(this.timer);
}
}
//处理点击
handleVote(id) {
//找到目标item
const newPosts = this.state.posts.map(item => {
const newItem = item.id === id ? {...item, vote: ++item.vote} : item;
return newItem;
});
//更新state中数据
this.setState({
posts: newPosts
});
}
render() {
return (
帖子列表:
{
this.state.posts.map(item =>
)
}
);
}
}
export default PostList;
升级之后的PostItme:
import React from 'react'
function PostItem(props) {
const handleClick = () => {
props.onVote(props.post.id);
};
const { post } = props;
return(
{post.title}
创建人:{post.author}
创建时间:{post.date}
{post.vote}
);
}
export default PostItem;
React提供了PropTypes这个对象,用于校验组件属性的类型。
PropTypes包含组件属性所有可能的类型,可以通过定义一个对象实现组件属性类型的校验。
使用PropTypes进行属性校验:
import React from 'react'
import PropTypes from 'prop-types'
class PostItem extends React.Component {
constructor(props) {
super(props);
console.log(JSON.stringify(props.post));
}
//定义点击事件
handleClick() {
this.props.onVote(this.props.post.id);
}
render() {
return(
{this.props.post.title}
创建人:{this.props.post.author}
创建时间:{this.props.post.date}
{this.props.post.vote}
);
}
}
//声明属性类型
PostItem.protoType = {
post: PropTypes.object,
onVote: PropTypes.func
}
export default PostItem;
也可对对象的属性进行校验,需要用到shape方法:
//声明属性类型
PostItem.protoType = {
//对象内属性校验
post: PropTypes.shape({
id: PropTypes.number,
title: PropTypes.string,
author: PropTypes.string,
date: PropTypes.string,
vote: PropTypes.number
}).isRequired,
//属性类型.是否必须
onVote: PropTypes.func.isRequired
}
使用组件样式有两种方式:一种是外部css样式表,另一种是内联样式。
此方式与开发Web应用时的方式相同,css样式表根据HTML标签类型、ID、class等选择器定义元素的样式。
唯一的区别是,React元素要使用className来作为class的选择器。
在src下创建style.css:
.testDiv {
width: 100%;
height: 50px;
background-color: blue;
}
使用该css:
import React from 'react';
import '../style.css'
function MyDiv(props) {
console.log("my div");
return Test;
}
export default MyDiv;
内联样式实际上是CSS in JS的写法:将CSS样式写到JS文件中,用JS对象表示CSS样式,然后通过DOM类型节点的sytle属性引用相应样式对象。
当使用内联样式的时候,样式的属性名必须使用驼峰格式的命名。例如,background-color要写成backgroundColor。
示例代码:
import React from 'react';
//声明样式
const style = {
width: "100%",
height: "50px",
backgroundColor: "red"
}
function AnthorMyDiv(props) {
return Test;
}
export default AnthorMyDiv;
React元素是一个普通的JS对象,这个对象通过DOM节点或React组件描述界面是什么样子。
JSX语法就是用来创建React元素的。
React组件是一个class或者函数,它接收一些属性作为输入,返回一个React元素。
React组件是由若干React元素组建而成的。