目录
一、组件的状态
在react中,组件分为有状态组件和无状态组件,具体为以下所示:
(1)函数组件又叫做无状态组件 函数组件在不考虑 hooks 的情况下是不能自己提供数据的;
(2)类组件又叫做有状态组件 类组件可以通过state自己提供数据;
(3)函数组件是没有状态的,只负责页面的展示;
(4)类组件有自己的状态,负责更新UI,只要类组件的数据发生了改变,UI 就会发生更新。
类组件的状态
(1)状态state,即数据,是组件内部的私有数据,只能在组件内部使用;
(2)状态 state 的值是对象,表示一个组件中可以有多个数据;
(3)通过 this.state.xxx 来获取状态。
class Hello extends React.Component {
state = {
count: 0,
};
render() {
return (
<>
<p>当前值为:{this.state.count}</p>
</>
);
}
}
ReactDOM.render(<Hello />, document.querySelector("#root"));
二、组件中的事件处理
1、事件绑定
(1)语法on+事件名 ={事件处理程序}比如onClick={this.handleClick};
(2)React事件采用驼峰命名法,比如onMouseEnter、onClick;
(3)函数式组件中不需要写this。
class Hello extends React.Component {
state = {
count: 0,
};
handelClick = () => {
console.log('Hello Word')
};
render() {
return (
<>
<p>当前值为:{this.state.count}</p>
<button onClick={this.handelClick}>按钮</button>
</>
);
}
}
2、事件处理与setState
事件对象
(1)可以通过事件处理程序的参数获取到事件对象;
(2)React 中的事件对象是 React 内部处理后的事件对象,用法与 DOM 原生的事件对象用法基本一致,例如: e.preventDefault()。
this指向
事件处理程序中的this指向的是undefined,render方法中的this指向的是当前react组件。只有事件处理程序中的this有问题。
解决方法:
(1)事件处理函数直接使用箭头函数即可;
(2)直接在标签内部写一个箭头函数,在剪头函数中调用事件处理函数(因为render中的this是没有问题的,而箭头函数沿用上层作用域中的this);
(3)使用bind改变this指向,绑定render中的this。
class Hello extends React.Component {
state = {
count: 0,
};
handelClick = () => {
console.log('Hello Word')
};
render() {
return (
<>
<p>当前值为:{this.state.count}</p>
<button onClick={() => this.handelClick()}>+1</button>
</>
);
}
}
setState 修改状态
语法:this.setState({ 要修改的部分数据 })
setState 是哪来的?从 Component 父类继承过来的,需要基于当前状态再做修改,不能直接修改(状态不可变概念)
class Hello extends React.Component {
state = {
count: 0,
};
handelClick = () => {
this.setState({
count: this.state.count + 1,
});
};
render() {
return (
<>
<p>当前值为:{this.state.count}</p>
<button onClick={() => this.handelClick()}>+1</button>
</>
);
}
}
三、非受控组件-Ref的使用
使用ref获取Dom
(1)调用 createRef 函数来创建一个 ref 对象
(2)ref 对象的名称(txtRef)可以是任意值
(3)current的值才是DOM对象
class Hello extends React.Component {
txtRef=createRef()
state = {
msg:'mo'
};
handelClick = () => {
console.log(this.txtRef.current.value);
};
handelChange = (e) => {
this.setState({
msg:e.target.value
})
console.log(this.state.msg);
}
render() {
return (
<>
<button onClick={() => this.handelClick()}>获取</button>
<input type='text' value={this.state.msg} ref={this.txtRef} onChange={this.handelChange}></input>
</>
);
}
}
四、组件通讯
1、父传子
(1)父组件提供要传递的state数据;
(2)给子组件标签添加属性,值为 state 中的数据;
(3)子组件中通过 props 接收父组件中传递的数据,函数组件时props.数据,类组件为this.props.数据。
const Child = (props) => {
return <p>姓名:{ props.name}</p>
}
class Hello extends React.Component {
txtRef=createRef()
state = {
name:'张家豪'
};
render() {
return (
<>
<Child name={this.state.name} />
</>
);
}
}
2、子传父
(1)父组件提供一个回调函数(用于接收数据);
(2)将该函数作为属性的值,传递给子组件;
(3)子组件通过 props 调用回调函数;
(4)将子组件的数据作为参数传递给回调函数。
const Child = (props) => {
console.log(props.getAge);
function handelClick() {
props.getAge(1);
}
return (
<>
<p>姓名:{props.name}</p>
<button onClick={handelClick}>返老还童</button>
</>
);
};
class Hello extends React.Component {
txtRef = createRef();
state = {
name: "张家豪",
age: 18,
};
getAge = (item) => {
this.setState({
age: this.state.age - item,
});
};
render() {
return (
<>
<p>年龄:{this.state.age}</p>
<Child name={this.state.name} getAge={this.getAge} />
</>
);
}
}
3、兄弟组件通讯
将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态,然后执行父传子、子传父实现兄弟组件之间的通讯,此处不做过多赘述。
4、跨级组件通讯
(1)导入creatContext;
import { createContext } from 'react';
(2)创建context对象,Provider提供状态,Consumer消费状态;
const { Provider, Consumer } = createContext();
(3)使用 Provider 组件包裹整个应用,并通过 value 属性提供要共享的数据;
(4)使用 Consumer 组件接收要共享的数据,以回调函数的形式。
const { Provider, Consumer } = createContext();
const Send = () => {
return <Consumer>{color => <p>{ color }</p> }</Consumer>
};
const Child = (props) => {
function handelClick() {
props.getAge(1);
}
return (
<>
<p>姓名:{props.name}</p>
<button onClick={handelClick}>返老还童</button>
<Send />
</>
);
};
class Hello extends React.Component {
txtRef = createRef();
state = {
name: "张家豪",
age: 18,
};
getAge = (item) => {
this.setState({
age: this.state.age - item,
});
};
render() {
return (
<>
<Provider value='green'>
<p>年龄:{this.state.age}</p>
<Child name={this.state.name} getAge={this.getAge} />
</Provider>
</>
);
}
}
五、总结
时间关系,本次只总结了这么多,下次将会介绍props的其他用法、setState进阶、组件的生命周期以及函数组件中Hooks的使用。
诸君,我们下期再见~