本文介绍react的重中之重,react的组件。组件是react的核心所在,第一部分先介绍组件的基础内容,并且做一个组件能实行盒子左右移动的组件box帮助理解组件内容。
第二部分介绍组件与组件之间的关系以及组件数据与函数的之间的相互调用。
1.安装bootstrap
库:
npm i bootstrap
bootstrap
的引入方式:
import 'bootstrap/dist/css/bootstrap.css';
2.创建 3.内嵌表达式 4.设置属性 5.数据驱动改变Style 6.渲染列表 7.Conditional Rendering 与表达式中 No colors 8.绑定事件 9.修改state 10.其它: 首先创建APP,Boxes,Navber组件,APP组件中包含着 Boxes组件和Navber组件,并且让Boxes组件中包含一系列Box组件。 1. 从上往下传递数据 App在Boxes标签中插入要传入的元素即可,可以传递变量,数据,函数,对象,类无论啥都可以传递。 App类组件中的render函数 Boxes里调用父组件的就是用 2.传递子节点 Boxes中的父标签插入子节点: Box标签调用子节点: 3.从下往上调用函数 4.state数据的存储 5.兄弟结点之间组件的调用 类似 Boxes和Navber 这两个组件,他们的公用数据都放在App组件中。 6.无状态函数组件 以Navber组件为例: 函数组件写法 (函数的传入参数为props对象) 7.组件的生命周期Component
创建按钮
当子节点数量大于1时,可以用
将其括起来。
import React, { Component } from 'react';
class Box extends Component
state = {
x : 0,
colors : [],
};
render() {
return (
JSX中使用{}嵌入表达式。 render() {
return (
class -> className
CSS属性:background-color -> backgroundColor,其它属性类似 render() {
return (
通过修改this.state.x的值,给样式修改不同的stylerender() {
return (
使用map函数
每个元素需要具有唯一的key属性,用来帮助React快速找到被修改的DOM元素。 state = {
x : 0,
colors : ['red','green','blue'],
};
render() {
return (
利用逻辑表达式的短路原则。expr1 && expr2
,当expr1
为假时返回expr1
的值,否则返回expr2
的值
或表达式中 expr1 || expr2
,当expr1
为真时返回expr1
的值,否则返回expr2
的值 state = {
x : 0,
colors : [],
};
{this.state.colors.length === 0 &&
注意妥善处理好绑定事件函数的this handleClickLeft = (step) => {
console.log(step);
console.log("click left",this);
}
handleClickRight = () => {
console.log("click right",this);
}
render() {
return (
需要使用this.setState()
函数
每次调用this.setState()
函数后,会重新调用this.render()
函数,用来修改虚拟DOM树。React只会修改不同步的实际DOM树节点。 handleClickLeft = (step) => {
this.setState({ //如果想要我们的修改改变render函数,需要调用一下setState
x : this.state.x - 1,
})
}
handleClickRight = () => {
this.setState({
x : this.state.x + 1,
})
}
render() {
return (
数组中用filter删除元素方法。
filter会帮我们遍历数组内的每一个值,如果返回值会false则保留,true则删除元素
state = {
solutions : [
{key : 0,number : 1164,title :"背包问题",views:2930},
{key : 1,number : 1165,title :"背包问题",views:2930},
{key : 2,number : 1166,title :"背包问题",views:2930},
{key : 3,number : 1166,title :"背包问题",views:2930},
{key : 4,number : 1167,title :"背包问题",views:2930},
{key : 5,number : 1168,title :"背包问题",views:2930},
{key : 6,number : 1169,title :"背包问题",views:2930},
{key : 7,number : 1113,title :"背包问题",views:2930},
],
}
handleClickdelete = (s) => {
const solutions = this.state.solutions.filter(solution => solution !== s); //filter会帮我们遍历数组内的每一个值,如果返回值会false则保留,true则删除元素
this.setState({
solutions : solutions,
}) ;
}
render{
...
}
二、Component的组合运用
通过this.props
属性可以从上到下传递数据。
此时Boxes为App的子结点,父节点传给子节点即可用props
属性。render() {
return (
<React.Fragment>
<NavBar boxesCount={this.state.boxes.length}/>
<Boxes
boxes={this.state.boxes}
onReset={this.handleReset}
onLeft={this.handleClickLeft}
onRight={this.handleClickRight}
onDelete={this.handleDelete}
/>
React.Fragment>
);
}
props
属性。
例子:class Boxes extends Component {
render() {
return (
<React.Fragment>
<button onClick={this.props.onReset} style={{marginBottom: "15px"}} className='btn btn-info'>Resetbutton>
{this.props.boxes.map(box => (
通过this.props.children
属性传递子节点
在上面Boxes组件中,我们在Box标签中间插入了其它标签,就是我们通过children传入给Box的子结点。 <Box key={box.id}>
<h1>Boxh1>
<p>#{box.id}p>
Box>
class Box extends Component {
state = {
};
render() {
return (
<React.Fragment>
{this.props.children}
React.Fragment>
);
}
}
注意:每个组件的this.state
只能在组件内部修改,不能在其他组件内修改。
例:Boxes组件调用父组件App的函数:<React.Fragment>
{this.props.boxes.map(box => (
每个维护的数据仅能保存在一个this.state
中
不要直接修改this.state的值,因为setState函数可能会将修改覆盖掉。
例如我们App组件中的handleClickLeft函数: handleClickLeft = (box) => {
const boxes = [...this.state.boxes]; //这里浅拷贝一个数组
const k = boxes.indexOf(box); //索引box的下标
boxes[k].x --; //修改box的x
this.setState({boxes : boxes}); // 传给setState 为什么这里要大费周折复制一个数组在赋值呢? 如果直接修改
// state的值,可能会让DOM的数值不同步,因为react的DOM树需要setState才能更换,所以这样做可以使数据保持同步
}
要将多个组件共用的数据存放到最近公共祖先的this.state
中。class App extends Component {
state = {
boxes : [
{id:1,x : 1},
{id:2,x : 2},
{id:3,x : 3},
{id:4,x : 4},
]
}
handleClickLeft = (box) => {
console.log("handle click left");
const boxes = [...this.state.boxes]; //这里浅拷贝一个数组
const k = boxes.indexOf(box); //索引box的下标
boxes[k].x --; //修改box的x
this.setState({boxes : boxes}); // 传给setState 为什么这里要大费周折复制一个数组在赋值呢? 如果直接修改
// state的值,可能会让DOM的数值不同步,因为react的DOM树需要setState才能更换,所以这样做可以使数据保持同步
}
handleClickRight = (box) => {
console.log("handle click right");
const boxes = [...this.state.boxes];
const k = boxes.indexOf(box);
boxes[k].x ++;
this.setState({boxes : boxes});
}
handleReset = () => {
const boxes = this.state.boxes.map(b=> {
return {
id: b.id,
x : 0
}
});
this.setState({boxes});
}
handleDelete = (boxId) => {
const boxes = this.state.boxes.filter(
b => b.id !== boxId
);
this.setState({boxes:boxes});
}
render() {
return (
<React.Fragment>
<NavBar boxesCount={this.state.boxes.length}/>
<Boxes
boxes={this.state.boxes}
onReset={this.handleReset}
onLeft={this.handleClickLeft}
onRight={this.handleClickRight}
onDelete={this.handleDelete}
/>
</React.Fragment>
);
}
}
当组件中没有用到this.state
时,可以简写为无状态的函数组件。
类组件写法
class NavBar extends Component {
state = { }
render() {
return (
<nav className="navbar navbar-light bg-light">
<div className="container-fluid">
<a className="navbar-brand">Navbar
<span>Boxes Count: {this.props.boxesCount}</span>
</a>
</div>
</nav>
);
}
}
const NavBar= (props) => {
return (
<nav className="navbar navbar-light bg-light">
<div className="container-fluid">
<a className="navbar-brand">Navbar
<span>Boxes Count: { props.boxesCount}</span>
</a>
</div>
</nav>
);
}
Mount
周期,执行顺序:constructor() -> render() -> componentDidMount()
Update
周期,执行顺序:render() -> componentDidUpdate()
Unmount
周期,执行顺序:componentWillUnmount()
总结