用function定义的组件没有实例,不存在this,所以除了props无法使用另外两个属性(通过hooks可以改变);
状态 state
案例一:通过点击文字切换天气状态
class Weather extends React.Component{
constructor(props){
super(props);
//初始化状态
this.state = {isHot:true,wind:'微风'};
//解决changeWeather中this的指向问题
this.changeWeather = this.changeWeather.bind(this);
}
render(){
const {inHot,wind} = this.state;
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
}
changeWeather(){
//类中的方法默认开启了严格模式,所以changeWeather中的this为undefined
//需要通过bind改变this的指向
const isHot = this.state.isHot;
//要使用setState修改
this.setState({isHot:!isHot});
}
}
ReactDOM.render(
<Weather />,
document.querySelector('#root')
)
简写以上代码:
//自定义事件往往作为事件回调使用
class Weather extends React.Component{
//初始化状态,可以直接赋值
state = {isHot:false,wind:'微风'}
render(){
const {isHot,wind} = this.state;
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
}
//以赋值的方式写
//由于箭头函数中没有this,会向外找实例,则指向Weather实例
//自定义方法 —— 要用赋值语句的形式 + 箭头函数
changeWeather = () =>{
const isHot = this.state.isHot;
this.setState({isHot:!isHot});
}
}
ReactDOM.render(
<Weather />,
document.querySelector('#root')
)
总结:
-
state的值是对象,包含多个键值对;
-
组件中的render方法的this为组件实例对象;
-
组件自定义方法的this为undefined:
a. 强制绑定this:通过函数对象的bind( )
b. 赋值语句+箭头函数
-
状态数据,不能直接修改或更新,要通过setState
传参 props
案例二:展示几个人的信息列表
class Person extends React.Component{
render(){
const {name,sex,age} = this.props;
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
//渲染组件到页面
ReactDOM.render(<Person name="jerry" age="19" sex = "男"/>,document.getElementById('test'))
}
批量传输props
//...展开运算符只能展开数组,不能展开对象,但是可以实现拷贝对象的作用
//let person2 = {...person} 实现了拷贝的作用
let people = {name:"jerry" age:"19" sex:"男"};
ReactDOM.render(<Person {...people}/>,document.getElementById('test'))
}
对props进行限制
//需要全局引入prop-types的js文件
//对props进行类型限定
Person.propTypes = {
name:PropTypes.string.isRequired, //限制姓名必传,且为字符串
sex:PropTypes.string,
age:PropTypes.number,
}
//给props定义默认值
Person.defaultProps = {
sex:"男",
age:18,
}
函数组件可以使用props
function Person(props){
const {name,age,sex} = props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
//渲染组件到页面
ReactDOM.render(<Person name="jerry" age="19" sex = "男"/>,document.getElementById('test'))
}
标识 refs
案例三:点击按钮,弹出input输入的相关信息
//字符串形式的ref(不推荐使用)
class Demo extends React.Component{
render(){
return (
<div>
<input ref="input" type="text"></input>
<button onClick={this.showData}>点击我显示数据</button>
</div>
)
}
showData = () =>{
const {input} = this.refs; //注意这里是refs,而不是ref
alert(input.value);
}
}
//回调形式的ref
//ref回调函数以内联函数方式定义时,更新过程会被执行两次,第一次清空传入参数null,第二次传入参数DOM元素
//可以以类class绑定函数的方式解决这种问题
class Demo extends React.Component{
render(){
return (
<div>
<input ref={c=>this.input=c } type="text"></input>
<button onClick={this.showData}>点击我显示数据</button>
</div>
)
}
showData = () =>{
const {input} = this;
alert(input.value);
}
}
//createRef的使用
class Demo extends React.Component{
//React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点
//该容器是专人专用,一个标签一个容器
myRef = React.createRef()
render(){
return (
<div>
<input ref={this.myRef} type="text"></input>
<button onClick={this.showData}>点击我显示数据</button>
</div>
)
}
showData = () =>{
alert(this.myRef.current.value);
}
}
React中的事件处理
-
通过onXXX属性指定事件处理函数(注意大小写)
a. React使用的是自定义事件,而不是原生的DOM事件——兼容性
b. React中的事件是通过事件委托的方式处理的(委托给最外层元素)——高效
-
通过event.target得到发生事件的DOM元素对象——不要过度使用ref,可以用event.target代替