1.1 创建项目
创建项目box-app:
create-react-app box-app
cd box-app
npm start
安装bootstrap库:
npm i bootstrap
bootstrap的引入方式(src/index.js):
import 'bootstrap/dist/css/bootstrap.css';
1.2 创建Component
在src目录下创建components目录,在components目录下创建box.jsx,类名为Box继承Component,在index.js里面调用Box
1.3 创建按钮
当子节点数量大于1时,可以用<div>
或<React.Fragment>
将其括起来,记得加括号。
class Box extends Component {
state = { }
render() {
return (
<React.Fragment>
<h1>Hello World</h1>
<button>left</button>
<button>right</button>
</React.Fragment>
);
}
}
1.4 内嵌表达式
JSX中使用{}嵌入表达式。即在html标签里写表达式,用大括号括起来
{}里面可以写表达式,类似于${}
例如:
class Box extends Component {
state = {
x : 1,
}
render() {
return (
<React.Fragment>
<h1>{this.toString()}</h1>
<button>left</button>
<button>right</button>
</React.Fragment>
);
}
toString(){
return "x:"+ this.state.x;
}
}
显示
1.5 设置属性
class -> className
CSS属性:background-color -> backgroundColor,其它属性类似
需要某个组件的样式,就可以在Bootstrap里面搜索,然后将对应的class复制过来即可
例如:
class Box extends Component {
state = {
x : 1,
}
render() {
return (
<React.Fragment>
<h1>{this.toString()}</h1>
<button className="btn btn-warning m-2">left</button>
<button className='btn btn-secondary m-2'>right</button>
</React.Fragment>
);
}
toString(){
return "x:"+ this.state.x;
}
}
1.6 数据驱动改变Style
style={{}},两层大括号,外层跟1.4一样,表示内嵌属性,用大括号括起来,内层的大括号代表一个对象。
例如:
class Box extends Component {
state = {
x : 1,
}
render() {
return (
<React.Fragment>
<div style={{
width:"50px",
height:"50px",
backgroundColor:"lightblue ",
color:"white",
textAlign:"center",
lineHeight:"50px",
borderRadius:"5px"
}}>{this.toString()}</div>
<button className="btn btn-warning m-2">left</button>
<button className='btn btn-secondary m-2'>right</button>
</React.Fragment>
);
}
toString(){
return "x:"+ this.state.x;
}
}
一般state里面的值用来控制改变style
例如:
class Box extends Component {
state = {
x : 0,
}
render() {
return (
<React.Fragment>
<div style = {this.getStyle()}>{this.toString()}</div>
<button className="btn btn-warning m-2">left</button>
<button className='btn btn-secondary m-2'>right</button>
</React.Fragment>
);
}
getStyle(){
let style={
width:"50px",
height:"50px",
backgroundColor:"lightblue ",
color:"white",
textAlign:"center",
lineHeight:"50px",
borderRadius:"5px"
}
if(this.state.x === 0) style.backgroundColor="orange";
return style;
};
toString(){
return "x:"+ this.state.x;
}
}
1.7 渲染列表
使用map
函数
每个元素需要具有唯一的key属性,用来帮助React快速找到被修改的DOM元素。
例如:
class Box extends Component {
state = {
x : 0,
colors : ["red", "green", "blue"],
}
render() {
return (
<React.Fragment>
<div style = {this.getStyle()}>{this.toString()}</div>
<button className="btn btn-warning m-2">left</button>
<button className='btn btn-secondary m-2'>right</button>
{this.state.colors.map(color => (
<div key={color}>{color}</div> //div没有key,会有一个warning
))}
</React.Fragment>
);
}
getStyle(){
let style={
width:"50px",
height:"50px",
backgroundColor:"lightblue ",
color:"white",
textAlign:"center",
lineHeight:"50px",
borderRadius:"5px"
}
if(this.state.x === 0) style.backgroundColor="orange";
return style;
};
toString(){
return "x:"+ this.state.x;
}
}
1.8 Conditional Rendering
利用逻辑表达式的短路原则。
与表达式中 expr1 && expr2,当expr1为假时返回expr1的值,否则返回expr2的值
或表达式中 expr1 || expr2,当expr1为真时返回expr1的值,否则返回expr2的值
例如:
class Box extends Component {
state = {
x : 0,
colors : [],
}
render() {
return (
<React.Fragment>
<div style = {this.getStyle()}>{this.toString()}</div>
<button className="btn btn-warning m-2">left</button>
<button className='btn btn-secondary m-2'>right</button>
{this.state.colors.length === 0 && <div>No color</div>} //this.state.colors.length === 0为真,返回<div>No color</div>
{this.state.colors.map(color => (
<div key={color}>{color}</div>
))}
</React.Fragment>
);
}
getStyle(){
let style={
width:"50px",
height:"50px",
backgroundColor:"lightblue ",
color:"white",
textAlign:"center",
lineHeight:"50px",
borderRadius:"5px"
}
if(this.state.x === 0) style.backgroundColor="orange";
return style;
};
toString(){
return "x:"+ this.state.x;
}
}
1.9 绑定事件
注意妥善处理好绑定事件函数的this
例如:
给按钮绑定点击事件
<button onClick={this.handleClickLeft}>left</button> //handleClickLeft是自己实现的函数,用来只想某些操作
1.10 修改state
需要使用this.setState()
函数
每次调用this.setState()
函数后,会重新调用this.render()
函数,用来修改虚拟DOM树。React只会修改不同步的实际DOM树节点。
例如:
class Box extends Component {
state = {
x : 0,
}
handleClickLeft = () => {
this.setState({
x : this.state.x - 1,
});
}
handleClickRight = () => {
this.setState({
x:this.state.x + 1
});
}
render() {
return (
<React.Fragment>
<div style = {this.getStyle()}>{this.toString()}</div>
<button onClick={this.handleClickLeft} className="btn btn-warning m-2">left</button>
<button onClick={this.handleClickRight} className='btn btn-secondary m-2'>right</button>
</React.Fragment>
);
}
getStyle(){
let style={
width:"50px",
height:"50px",
backgroundColor:"lightblue ",
color:"white",
textAlign:"center",
lineHeight:"50px",
borderRadius:"5px",
marginLeft: this.state.x //随着x的变化,方块的位置也会移动
}
if(this.state.x === 0) style.backgroundColor="orange";
return style;
};
toString(){
return "x:"+ this.state.x;
}
}
点击left或者right会改变x的值,蓝色区域会随着x的改变左右移动
1.11 给事件函数添加参数
新增一个函数做中介,在标签内调用这个中介函数
例如:
class Box extends Component {
state = {
x : 0,
}
handleClickLeft = (step) => {
this.setState({
x : this.state.x - step,
});
}
handleClickRight = () => {
this.setState({
x:this.state.x + 1
});
}
handleClickLeftTmp = () => { //中介
return this.handleClickLeft(10);
}
render() {
return (
<React.Fragment>
<div style = {this.getStyle()}>{this.toString()}</div>
<button onClick={this.handleClickLeftTmp} className="btn btn-warning m-2">left</button>
<button onClick={this.handleClickRight} className='btn btn-secondary m-2'>right</button>
</React.Fragment>
);
}
getStyle(){
let style={
width:"50px",
height:"50px",
backgroundColor:"lightblue ",
color:"white",
textAlign:"center",
lineHeight:"50px",
borderRadius:"5px",
marginLeft: this.state.x //随着x的变化,方块的位置也会移动
}
if(this.state.x === 0) style.backgroundColor="orange";
return style;
};
toString(){
return "x:"+ this.state.x;
}
}
或者将这个中介函数写成匿名函数的形式,不显示的定义出来
<button onClick={ () => this.handleClickLeft(10)} className="btn btn-warning m-2">left</button>
<button onClick={ () => this.handleClickRight(10)} className='btn btn-secondary m-2'>right</button>