组件实例的三大属性
1.属性一
state
【概念】React 把组件看成是一个状态机。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
【注意】
- 组件中render方法中的this为组件实例对象
- 组件自定义的方法中this为undefined,如何解决?
a. 强制绑定this:通过函数对象的bind()
b. 箭头函数- 状态数据,不能直接修改或更新
- 不要直接修改State,而是使用setState()
2.属性二
props
子组件只能通过 props 来传递数据
<script type="text/babel">
//1.创建组件
class Person extends React.Component {
render() {
const {name,age} = this.props;
return (
<div>
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
</ul>
</div>
)
}
}
//对标签属性进行类型|必要性的限制(这里需要引入PropTypes的React库文件)
Person.propTypes = {
name: PropTypes.string.isRequired,
sex: PropTypes.string,
age: PropTypes.number,
speak: PropTypes.func
}
//对标签属性进行类型、必要性的限制
Person.defultProps = {
sex:'女',
age:18
}
//2.渲染组件到页面
ReactDOM.render(<Person name="张三" age="14"/>, document.getElementById('test1'));
ReactDOM.render(<Person name="老王" age="18"/>, document.getElementById('test2'));
function speak(){
console.log('我说话了');
}
</script>
props简写方式(把所有的限制放在类的里边)
<script type="text/babel">
//1.创建组件
class Person extends React.Component {
//对标签属性进行类型|必要性的限制
static propTypes = {
name: PropTypes.string.isRequired,
sex: PropTypes.string,
age: PropTypes.number,
speak: PropTypes.func
}
//对标签属性进行类型、必要性的限制
static defultProps = {
sex:'女',
age:18
}
render() {
const {name,age} = this.props;
return (
<div>
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
</ul>
</div>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Person name="张三" age="14"/>, document.getElementById('test'));
function speak(){
console.log('我说话了');
}
</script>
3.属性三
ref
ref是React提供的用来操纵React组件实例或者DOM元素的接口。
ref的三种方式
字符串形式的ref
<script type="text/babel">
//1.创建组件
class Demo extends React.Component {
showIputDate = () => {
const {input2} = this.refs;
alert(input2.value);
}
render() {
return (
<div>
<input onBlur={this.showIputDate} ref="input2" type="text" placeholder="失去焦点获取内容" />
</div>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Demo/>, document.getElementById('test'));
</script>
回调形式的ref
<script type="text/babel">
//1.创建组件
class Demo extends React.Component {
showDate = () => {
const {input} = this;
alert(input.value);
}
showIputDate2 = () => {
const {input3} = this;
alert(input3.value);
}
render() {
return (
<div>
<input type="text" ref={(e)=>{this.input=e;console.log("@",e)}} placeholder="点击按钮获取内容" />
<button onClick={this.showDate}>按钮</button>
<input onBlur={this.showIputDate2} ref={(c) => {this.input3 = c}} type="text" placeholder="失去焦点获取内容" />
</div>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Demo/>, document.getElementById('test'));
</script>
ceateRef的使用
<script type="text/babel">
//1.创建组件
class Demo extends React.Component {
/*
React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点
*/
myRef = React.createRef();
myRef2 = React.createRef();
showDate = () =>{
alert(this.myRef.current.value);
}
showIputDate2 = () =>{
alert(this.myRef2.current.value);
}
render() {
return (
<div>
<input type="text" ref={this.myRef} placeholder="点击按钮提示数据" />
<button onClick={this.showDate}>按钮</button>
<input onBlur={this.showIputDate2} ref={this.myRef2} type="text" placeholder="失去焦点获取内容" />
</div>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Demo/>, document.getElementById('test'));
</script>
【强调】勿过度使用refs
非受控组件与受控组件
非受控组件
<script type="text/babel">
class Login extends React.Component{
onLogin = (event) => {
//阻止表单提交
event.preventDefault();
const {username,password} = this;
alert(`你输入的用户名是${username.value},密码是${password.value}`)
}
render() {
return (
<form action="https://baidu.com" onSubmit={this.onLogin}>
用户名: <input ref={c => this.username=c} type="text" name="username"/>
密码:<input ref={c => this.password=c} type="text" name="password"/>
<button>提交</button>
</form>
)
}
}
ReactDOM.render(<Login/>,document.getElementById('test'));
</script>
受控组件
<script type="text/babel">
class Login extends React.Component{
// 获取用户名到state
changeUsername = (event) => {
this.setState({username:event.target.value});
}
// 获取密码到state
changePassword = (event) => {
this.setState({password:event.target.value});
}
onLogin = (event) => {
//阻止表单提交
event.preventDefault();
const {username,password} = this.state;
alert(`你输入的用户名是${username},密码是${password}`)
}
render() {
return (
<form action="https://baidu.com" onSubmit={this.onLogin}>
用户名: <input onChange={this.changeUsername} type="text" name="username"/>
密码:<input onChange={this.changePassword} type="text" name="password"/>
<button>提交</button>
</form>
)
}
}
ReactDOM.render(<Login/>,document.getElementById('test'));
</script>
概念
高阶函数与函数的柯里化
高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。
- 若A函数,接受的参数是一个函数,那么A就是可以称之为高阶函数。
- 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
a.常见的高阶函数有:Promise
、setTimeout
、arr.map()
等等函数的柯里化:通过函数调用继续返回函数方式,实现多次接受参数最后统一处理的函数编码形式。
例子
class Login extends React.Component{
// 初始化状态
state = {
username:'', //用户名
password: '' // 密码
}
// 获取表单数据到状态中
saveFromDate = (typeDate) => {
return(event)=>{
this.setState({[typeDate]:event.target.value});
}
}
onSubmit = (event) => {
//阻止表单提交
event.preventDefault();
const {username,password} = this.state;
alert(`你输入的用户名是${username},密码是${password}`)
}
render() {
return (
<form action="https://baidu.com" onSubmit={this.onSubmit}>
用户名: <input onChange={this.saveFromDate('username')} type="text" name="username"/>
密码:<input onChange={this.saveFromDate('password')} type="text" name="password"/>
<button>提交</button>
</form>
)
}
}
ReactDOM.render(<Login/>,document.getElementById('test'));
不用函数的柯里化实现
、<script type="text/babel">
class Login extends React.Component{
// 初始化状态
state = {
username:'', //用户名
password: '' // 密码
}
// 获取表单数据到状态中
saveFromDate = (typeDate,event) => {
this.setState({[typeDate]:event.target.value});
}
onSubmit = (event) => {
//阻止表单提交
event.preventDefault();
const {username,password} = this.state;
alert(`你输入的用户名是${username},密码是${password}`)
}
render() {
return (
<form action="https://baidu.com" onSubmit={this.onSubmit}>
用户名: <input onChange={event => this.saveFromDate('username',event)} type="text" name="username"/>
密码:<input onChange={event => this.saveFromDate('password',event)} type="text" name="password"/>
<button>提交</button>
</form>
)
}
}
ReactDOM.render(<Login/>,document.getElementById('test'));
</script>
react生命周期(旧与新)
- 组件从创建到死亡它会经历一些特定的阶段
- React组件中包含一系列钩子函数的生命周期,会在特定的时刻调用
- 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作
生命周期(旧)
- 初始化阶段:由ReactDOM.render()触发—初次渲染
1)constructor()
2) componentWillMount()
3) render()
4) componentDidMount() ====> 常用
一般在这个钩子中做一些初始化的事,例如:开启定时器、 送网络请求、订阅消息- 更新阶段:由组件内部this.setSate()或父组件render触发
1) shouldComponentUpdate()
2) componentWillUddate()
3) render() ====> 必须使用的一个
4)componentDidUpdate()- 卸载组件:由ReactDOM.unmountComponentAtNode()触发
1) componentWillUnmount() ====> 常用
一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
例子
<script type="text/babel">
//创建组件
class Sum extends React.Component{
//构造器
constructor(props){
console.log('count---constructor');
super(props)
// 初始化状态
this.state = {count:0};
}
//加1按钮的回调
add = ()=>{
//获取原状态
let {count} = this.state;
//更新状态
this.setState({count:count+1})
}
//卸载组件按钮的回调
death = ()=>{
ReactDOM.unmountComponentAtNode(document.getElementById('test'));
}
//强制更新按钮的回调
force = ()=>{
this.forceUpdate();
}
//组件将要挂载的钩子
componentWillMount(){
console.log('count---componentWillMount');
}
//组件将要挂载完毕的钩子
componentDidMount(){
console.log('count---componentDidMount');
}
//组件将要卸载的钩子
componentWillUnmount(){
console.log('count---componentWillUnmount');
}
//控制组件更新的“阀门”
shouldComponentUpdate(){
console.log('count---shouldComponentUpdate');
return true;
}
//组件将要更新的钩子
componentWillUpdate(){
console.log('count---componentWillUpdate');
}
//组件更新完毕的钩子
componentDidUpdate(){
console.log('count---componentDidUpdate');
}
render() {
console.log('count---render');
return (
<div>
<h2>当前求和为{this.state.count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
</div>
)
}
}
//父组件A
class A extends React.Component{
//初始化状态
state = {carName:'奔弛'}
changeCar = ()=>{
this.setState({carName:'奥拓'})
}
render(){
return(
<div>
<div>我是A组件</div>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName}/>
</div>
)
}
}
//子组件B
class B extends React.Component{
//组件将要接受新的props的钩子
componentWillReceiveProps(props){
console.log('B---componentWillReceiveProps',props);
}
//控制组件更新的“阀门”
shouldComponentUpdate(){
console.log('B---shouldComponentUpdate');
return true;
}
//组件将要更新的钩子
componentWillUpdate(){
console.log('B---componentWillUpdate');
}
//组件更新完毕的钩子
componentDidUpdate(){
console.log('B---componentDidUpdate');
}
render(){
console.log('B---render');
return(
<div>我是B组件,接受到的车:{this.props.carName}</div>
)
}
}
//渲染组件
ReactDOM.render(<A/>,document.getElementById('test'));
// ReactDOM.render(<Sum/>,document.getElementById('test'));
</script>
生命周期(新)
生命周期新与旧版本的区别:
- 新版本即将废弃三个生命钩子:componentWillUnmount、componentWillUpdate和componentWillReceiveProps
- 提出2个新的生命钩子:getDerivedStateFromProps和getSnapshotBeforeUpdate