1、state
state
是组件对象最重要的属性,值是对象(可以包含多个key-value的组合)
组件被称为"状态机",通过更新组件的state
来更新对应的页面显示(重新渲染组件)
用state来初始化状态,用setState这个API来对状态进行更改
最原始的写法:
对于类来说,状态一般是维护在constructor函数中的,对于继承的类来说,constructor函数可有可无,如果写了就一定要调用super方法
<script type="text/babel">
class Weather extends React.Component {
constructor(props) {
// 构造器调用几次 —— 1次
super(props)
// 初始化状态
this.state = {isHot:true}
// 解决changeWeather中this指向问题
this.changeWeather = this.changeWeather.bind(this)
}
render() {
// render调用几次 —— 1+n次 1是初始化的时候调用,n是状态更新的次数
// 读取状态
const {isHot} = this.state
return <h2 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
}
changeWeather() {
// changeWeather调用几次 —— 点击几次调几次
// changeWeather放在Weather的原型对象上,供实例使用
// 由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
// 类中方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
// 获取原来的isHot值
const isHot = this.state.isHot
// 严重注意:state不可直接更改,必须通过setState进行更新,且更新是一种合并不是替换
this.setState({isHot:!isHot})
}
}
</script>
简写:
<script type="text/babel">
class Weather extends React.Component {
// 类中可以直接写赋值语句,含义是给类的实例对象添加一个属性
state = {isHot:true,wind:'微风'}
render() {
const {isHot,wind} = this.state
return <h2 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h2>
}
// 自定义方法——要用赋值语句的形式+箭头函数
changeWeather = () => {
const isHot = this.state.isHot
this.setState({isHot:!isHot})
}
}
</script>
强烈注意点:
- 组件render方法中this为组件实例对象
组件自定义的方法中this为undefined,如果解决?
- 强制绑定this,通过函数对象的bind
- 箭头函数
- 状态数据,不能直接修改或更新
2、props
每个组件对象都会有props属性,组件标签的所有属性都保存在props中
通过标签属性从组件外向组件内传递变化的数据,注意:组件内部不要修改props数据
1、基本使用
ReactDOM.render(<Person name="tom" age="18" sex="男" />,
2、批量传递
const p = {name:'老刘',age:18,sex:'男'}
ReactDOM.render(<Person {...p} />,document.getElementById('test2'))
3、对props
进行限制
// 对标签属性进行类型、必要性的限制
Person.propTypes = {
name:PropTypes.string.isRequired, // 限制name必传且为字符串
sex:PropTypes.string,
age:PropTypes.number,
speak:PropTypes.func, // 限制speak为函数
}
// 指定默认标签属性值
Person.defaultProps = {
sex:"男",
age:18
}
4、props
的简写方式
<script type="text/babel">
class Person extends React.Component {
constructor(props) {
// 构造器是否接收props,是否传递给super,取决于是否希望在构造器中通过this访问props
super(props)
}
// 对标签属性进行类型、必要性的限制
static propTypes = {
name: PropTypes.string.isRequired, // 限制name必传且为字符串
sex: PropTypes.string,
age: PropTypes.number,
}
// 指定默认标签属性值
static defaultProps = {
sex: "男",
age: 18
}
render() {
const { name, age, sex } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age + 1}</li>
</ul>
)
}
}
3、refs
1、字符串形式的ref
官方推荐尽量避免使用
<input ref="input1" type="text" placeholder="点击按钮提示数据" />
2、回调函数形式的ref
回调函数内联写法存在调用次数的问题,也可以把回调函数写出来,但是内联写法存在的问题基本可以忽略,开发中也常用
<input ref={c => this.input1 = c} type="text" placeholder="点击按钮提示数据" />
3、createRef
React.createRef()调用后可以返回一个容器,该容器可以存储被ref所标识的节点,但该容器是 "专人专用" 的
<script type="text/babel">
class Demo extends React.Component {
myRef = React.createRef()
myRef2 = React.createRef()
render() {
return (
<div>
// 通过this.myRef.current.value拿到数据
<input ref={this.myRef} type="text"/>
<input ref={this.myRef2} type="text"/>
</div>
)
}
}
</script>