组件的状态
组件都可以自行的维护自己的数据,尽量在内组件中使用
状态:本质上就是类组件的一个属性,就是一个对象
状态的初始化:
constructor 中 this.state = {}
类中 state = {} jsnext语法,试验阶段,都可以写,最后都要被babel编译
状态的变化:
不能直接去改变状态中的数据,因为react无法监控到状态中数据的变化,必须使用this.setState({})改变数据,如果对比数据变化,则不会动对象,考虑效率。一旦使用this.setState,会导致当前的组件重新渲染
组件中的数据
props 组件之间传递的数据,所有权是别人,没有权利更改
state 组件自己本身创建的数据,所有权是自己,有权利更改
下面写的是一个小dome
见代码:
import React from 'react';
import ReactDOM from 'react-dom';
import Tndexaa from './Tndexaa';
ReactDOM.render(<Tndexaa number={20}></Tndexaa>, document.getElementById('root'));
import React, { Component } from 'react'
export default class Tndexaa extends Component {
state = { //js next语法,目前处于试验阶段
left : this.props.number
}
// 1.接收数据
constructor(props){
super(props);
// 状态的初始化
this.state = {
left : this.props.number
}
this.timer = setInterval(() => {
// react中要修改组件的数据
this.setState({
// minix 混合 有相同的就覆盖 相当于object.assign()
left : this.state.left -1
})
if(this.state.left == 0){
clearInterval(this.timer)
}
},1000)
}
render() {
return (
<div>
倒计时剩余时间{this.state.left}
</div>
)
}
}
再看一个栗子:
import React from 'react';
import ReactDOM from 'react-dom';
import Tndexbb from './Tndexbb';
ReactDOM.render(<Tndexbb></Tndexbb>, document.getElementById('root'));
import React, { Component } from 'react'
export default class Tndexbb extends Component {
state = {
n : 123
}
constructor(props){
super(props);
setInterval(() => {
this.setState({
n : this.state.n -1
})
},1000);
}
render(){
console.log("A渲染了")
return(
<div>
A组件:{this.state.n}
<B n={this.state.n}/>
</div>
)
}
}
function B (props){
return(
<div>
B组件:{props.n}
<C n={props.n}/>
</div>
)
}
function C (props){
return(
<div>
C组件:{props.n}
</div>
)
}
事件
在react中,组件的事件,本质上就是一个属性,遵循react规范,使用小驼峰命名
内置组件的事件绑定:
import React from 'react';
import ReactDOM from 'react-dom';
function a(){
console.log("点击了")
}
const btn = <button onClick={a} onMouseEnter = {() => {
console.log("移入了")
}}>点击</button>
ReactDOM.render(btn, document.getElementById('root'));
看下面这个小dome:
index.js中
import React from 'react';
import ReactDOM from 'react-dom';
import Tndexbb from "./Tndexbb";
ReactDOM.render(<Tndexbb/>, document.getElementById('root'));
Tndexaa中
import React, { Component } from 'react'
export default class Tndexaa extends Component {
constructor(props){
super(props);
this.state = {
number : props.number
}
const timer = setInterval(() => {
this.setState({
number : this.state.number -1
})
if(this.state.number === 0){
clearInterval(timer);
this.props.abc && this.props.abc()
}
},1000)
}
render() {
return (
<div>
{/* 要用就必须落实到内置的react元素上面 */}
<h1 onClick = {this.props.onClick}>
倒计时:{this.state.number}
</h1>
</div>
)
}
}
Tndexaa中
import React, { Component } from 'react'
import Tndexaa from './Tndexaa';
export default class Tndexbb extends Component {
state = {
isOVer : false //倒计时是否完成
}
render() {
let status = "正在倒计时";
if(this.state.isOVer){
status = "倒计时完成"
}
return (
<div>
<Tndexaa number = {5} abc={() => {
this.setState({
isOVer : true
})
}}
//onclick只是一个属性,最终还要转化成react元素,要想使用,必须放在对应的内置react元素上面
onClick = {()=>{
console.log("点击了")
}}/>
<h2>{status}</h2>
</div>
)
}
}
运行效果如下:
点击后:
解决this的指向问题
bind
bind的第一种写法
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this)
this.handleOver = this.handleOver.bind(this)
}
render() {
let status = "正在倒计时";
if(this.state.isOVer){
status = "倒计时完成"
}
return (
<div>
<Tndexaa
number = {5}
// onClick = {this.handleClick}
// onOver = {this.handleOver}
// bind的第二种写法,第一种复杂,但效率高一些;第二种简单,但效率低,没次都进行了重新的绑定
onClick = {this.handleClick.bind(this)}
onOver = {this.handleOver.bind(this)}
/>
<h2>{status}</h2>
</div>
)
}
箭头函数
state = {
isOVer : false
}
//箭头函数的写法 js next语法
handleClick = () => {
console.log(this)
console.log("点击了")
}
handleOver = () => {
this.setState({
isOver : true
})
}