React-class——React表单与事件(受控组件与非受控组件、事件类型、事件对象、事件绑定)、React组件生命周期、面试

2023年1月10日07:57:29

目录

一、React表单与事件

1、React表单组件

(1)受控组件与非受控组件——笔试题

(2)更多受控组件

2、React事件

(1)事件类型

(2)事件对象

(3)事件绑定——this为unde

二、React组件生命周期

 1、组件的生命周期

 2、生命周期钩子详解

- **componentWillMount** :

- **componentDidMount** :

- **componentWillReceiveProps** :

- **shouldComponentUpdate** :

- **componentWillUpdate**:

render函数 在这中间执行

- **componentDidUpdate** :

- **componentWillUnmount**:

 3、生命周期钩子——网络请求


一、React表单与事件

1、React表单组件

在HTML中,表单元素与其他元素最大的不同是它自带值或数据

而且,只要是有表单出现的地方,就会有用户输入,表单事件触发,就会涉及的数据处理。

在我们用React开发应用时,为了更好地管理应用中的数据,响应用户的输入,编写组件的时候呢,我们就会运用到**受控组件与非受控组件**这两个概念。

React推荐我们在绝大多数情况下都使用受控组件。这样可以保证表单的数据在组件的state管理之下,而不是各自独立保有各自的数据。

(1)受控组件与非受控组件——笔试题

没有v-model,需要自己去实现

**受控组件**简单来说就是它的值由React进行管理,

而**非受控组件**的值则由原生DOM进行管理。

- 受控组件:==>双向

一般涉及到表单元素时我们才会使用这种分类方法。

受控组件的值由props或state传入给受控组件(表单的输入框),用户在元素上交互或输入内容会引起应用state的改变。

在state改变之后重新渲染组件,我们才能在页面中看到元素中值的变化,

假如组件没有绑定事件处理函数改变state,用户的输入是不会起到任何效果的,这也就是“受控”的含义所在。

- 非受控组件:==>单向

类似于传统的DOM表单控件,用户输入不会直接引起应用state的变化,我们也不会直接为非受控组件传入值。

 想要获取非受控组件,我们需要使用一个特殊的ref属性,同样也可以使用defaultValue属性来为其指定一次性的默认值。

示例如下:

import React from "react"
class App extends React.Component {
    constructor(arg) {
        super(arg)
        this.state = {}
        this.handleChange = (e) => {
            this.setState({ value: e.target.value });
            // e.target.value就是输入的值
        }
    }
    render() {
        return (
            <div>
                {/* 1、受控组件 */}
                <input type='text' value={this.state.value} onChange={this.handleChange} />

                {/* 2、非受控组件 */}
                <input type="text" value={this.state.value} />
                {/* 如果上没有onChange事件,输入框不能输入,value会一直是this.state.value */}
                <input type="text" defaultValue="hello!" />
            </div>
        )
    }
}
export default App

(2)更多受控组件

在组件中声明表单元素(input_type/checked   textarea  select ……)时,一般都要为表单元素传入应用状态中的值,我们需要根据表单元素中用户的输入,对应用数据进行相应的操作和改变。

1、radio:

class MyApp extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			gender: ''
		};
        this.handleGender = this.handleGender.bind(this);
	}
    handleGender(event) {
		this.setState({gender: event.target.value});
	}

	render() {
		return (
			<div>
                <h2>input_checked 受控组件</h2>
                <input type='radio' value="man" checked={this.state.gender=='man'} onChange={this.handleGender}/>男<br />
                <input type='radio' value="woman" checked={this.state.gender=='woman'} onChange={this.handleGender}/>女<br />
				<div>{this.state.gender}</div>
                
			</div>
		);
	}
}

ReactDOM.render(
	<MyApp />,
	document.getElementById('root')
);

2、mycheck:

import React, { Component } from 'react'
export default class Mycheck extends Component {
    constructor(){
        super()
        this.state={
            chengdu:true
        }
        this.chengduchange=(e)=>{
           console.log(e.target.checked)
           this.state.chengdu=e.target.checked
           this.setState(this.state)
        }
    }
  render() {
    return (
      <div>
        <input type="checkbox" name='city' value="chengdu" checked={this.state.chengdu} onChange={this.chengduchange}/>
        <input type="checkbox" name='city' value="shanghai"/>
        <input type="checkbox" name='city' value="beijing"/>
        <input type="checkbox" name='city' value="tianjing"/>
      </div>
    )
  }
}

3、mydata

import React, { Component } from 'react'
export default class Mydate extends Component {
    constructor(){
        super()
        this.state={
            v:"2021-11-11"
        }
        this.change1=(e)=>{
              console.log(e.target.value)
              this.state.v=e.target.value
              this.setState(this.state)
        }
    }
  render() {
    return (
      <div>
        <input type="date" value={this.state.v} onChange={this.change1}/>
      </div>
    )
  }
}

4、myfile

import React, { Component } from 'react'
export default class Myfile extends Component {
    constructor(){
        super()
        this.state={
            v:""
        }
        this.change1=(e)=>{
            console.log(e.target.files[0])
           this.state.v=e.target.files[0]
           this.setState(this.state)
        }
    }
  render() {
    return (
      <div>
        <input type="file" onChange={this.change1}/>
      </div>
    )
  }
}

5、myselect

import React, { Component } from 'react'
export default class Myselect extends Component {
    constructor(){
        super()
        this.state={
            v:"beijing"
        }
        this.change1=(e)=>{
          console.log(e.target.value)
          this.state.v=e.target.value
          this.setState(this.state)
        }
        this.send=()=>{
          console.log(this.state.v)
        }
    }
  render() {
    return (
      <div>
        <select name="city" value={this.state.v} onChange={this.change1}>
            <option value="chengdu">成都</option>
            <option value="beijing">北京</option>
            <option value="shanghai">上海</option>
        </select>
        <button onClick={this.send}>发送</button>
      </div>
    )
  }
}

7、mytext

import React, { Component } from 'react'
export default class Mytext extends Component {
    constructor(arg){
        super(arg)
        this.state={msg:"66666"}
        this.input1=(e)=>{
          console.log(e.target.value)
          this.state.msg=e.target.value
          this.setState(this.state)
        }
      }
    render() {
        return (
            <div>
                <p>{this.state.msg}</p>
                <input type="text" value={this.state.msg} onInput={this.input1} />
                <input type="text" />
            </div>
        )
    }
}

2、React事件

(1)事件类型

使用React元素处理事件与处理DOM元素上的事件非常相似。不过有一些语法上的差异:

- React事件使用**小驼峰命名法**,而不是全部小写命名。
- React事件使用JSX传递一个函数作为事件处理程序,而不是一个字符串。

示例:

- 鼠标事件:onClick   onDoubleClick  onMouseDown
- 触摸事件:onTouchStart   onTouchMove   onTouchEnd 
- 键盘事件:onKeyDown 
- 剪切事件:onCopy   onCut     onPaste 
- 表单事件:onChange    onInput   onSubmit 
- 焦点事件:onFocus 
- UI事件:onScroll 
- 滚动事件:onWheel

(2)事件对象

构造函数:fun

- React对原生的事件系统也进行了封装,在React中的事件对象实际上是一个跨浏览器的**虚拟事件对象** ,它拥有和原生事件对象相同的属性和方法。

- 在react 中使用“return false” 无法阻止默认事件,只能通过事件对象调用“event.preventDefault() ”进行阻止

class ClickEvent extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			value: 'hello world'
		};
        //函数写法==> 方法1:
		this.changeData = this.changeData.bind(this);
        //方法2:
        this.fm=()=>{}
	}

    //方法3:
	changeData(event) {
//changeData函数也可以写在构造函数constructor内,写this.changeData都能调用到这个给函数
        console.log(event)
		this.setState({value: '萨瓦迪卡'});
	}
    fn(arg){}
    //方法4:
    fn1=function(){}
    //方法5:
    fn2=()=>{}
	render() {
		return (
			<div>
				<button onClick={this.changeData}>点击改变</button>
				<h2>{this.state.value}</h2>
                 //方法6:因为react中函数不能写小括号,所以自己设计,去实现有小括号,传参
                <button onClick={(e)=>{this.fn(100)}}>函数传参</button>
			</div>
		);
	}
}

(3)事件绑定——this为unde

事件处理函数内部使用this 关键词时其指向==>

class ClickEvent extends React.Component {
    constructor(arg) {
        super(arg)
        this.changeData=function (){console.log(this);}  //undefined
    }
	changeData() {
        console.log(this);//undefined
	}
	render() {
		return (
			<div>
				<button onClick={this.changeData}>点击改变</button>
			</div>
		);
	}
}

解决方法:

1、将函数写在constructor 内部,对事件处理函数bind 绑定this(官方推荐)

2、 每次事件绑定都对事件处理函数做bind 绑定

3、定义事件处理函数时使用箭头函数

<button onClick={e=>this.changeData.call(this)}>点击改变</button>

当事件处理函数需要传参时:

<button onClick={this.changeData.bind(this,id)}>点击改变</button>
 //将changeData处理为有this
<h2>{e=>this.changeData.call(id,event)}</h2>
//又想传参又要处理this,就用call
import React, { Component } from 'react'
export default class App extends Component {
  constructor() {
    super()
    this.fn = () => {
      console.log(1111, this.state)
    }
    this.fn3 = function () {
      console.log(333, this.state)
    }.bind(this)
    // this.state={}
  }
  fn2() {
    console.log(2222, this.state)
  }
  fn4 = function () {
    console.log(44444, this)
  }
  fn5 = () => {
    console.log(555, this)
  }
  fn6(arg) {
    console.log(arg)
  }
  fn7(id) {
    console.log(id)
  }
  state = { msg: "hello", arr: [{ id: 123, title: "a" }, { id: 124, title: "bb" }] }
  render() {
    return (
      <div>
        <button onClick={this.fn}>btn</button>
        <button onClick={this.fn2.bind(this)}>btn2</button>
        <button onClick={this.fn3}>btn3</button>
        <button onClick={this.fn4.bind(this)}>btn4</button>
        {/* <button onClick={(e)=>{this.fn4(this,e)}}>btn4</button> */}
        <p>{this.state.msg}</p>
        <button onClick={this.fn5}>btn5</button>
        <button onClick={(e) => { this.fn6(100) }}>btn6</button>
        {
          this.state.arr.map(el => (<div key={el.id}>
            <p>{el.title}</p>
            <button onClick={(e) => { this.fn7(el.id) }}>btn</button>
          </div>))
        }
      </div>
    )
  }
}

二、React组件生命周期

render函数 在页面初次加载的时候,会运行;数据每改变一次,页面刷新的时候也会运行。

构造函数只会调用一次,从创建到销毁都只调用一次。

 1、组件的生命周期

- Mounting:已插入真实 DOM

- Updating:正在被重新渲染

- Unmounting:已移出真实 DOM

  • 组件创建阶段(初始加载):一辈子只执行一次 构造函数(有争议,因为构造函数不算生命周期函数)、componentWillMount: render: componentDidMount:

  • 组件运行阶段:按需,根据props 属性或state 状态的改变,有选择性的执行0 到多次 componentWillReceiveProps: shouldComponentUpdate: componentWillUpdate: render: componentDidUpdate:

  • 组件销毁阶段:一辈子只执行一次

  • 因为没有了创建前后,想做预加载,就在构造函数或者componentWillMount中做

 2、生命周期钩子详解

定义:在特定的阶段,你刚刚自动执行的函数(方法)

- **componentWillMount** :

在渲染前调用,在客户端也在服务端。


- **componentDidMount** :

在**第一次渲染后**调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异部操作阻塞UI)。


- **componentWillReceiveProps** :

在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。


- **shouldComponentUpdate** :

自己判断是否需要刷新

返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。 可以在你确认不需要更新组件时使用。


- **componentWillUpdate**:

准备更新

在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。

render函数 在这中间执行


- **componentDidUpdate** :

已经更新,数据已经改完了

在组件完成更新后立即调用。在初始化时不会被调用。


- **componentWillUnmount**:

即将销毁

在组件从 DOM 中移除的时候立刻被调用。

class MyApp extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			date: new Date()
		};
	}
	//通过componentDidMount 方法设置一个定时器,每隔1秒重新设置时间,并重新渲染:
	componentDidMount() {
		var oThis=this;
		clearInterval(this.timer);

		this.timer=setInterval(function() {
			oThis.setState({
				date: new Date()
			})
		}, 1000)
	}
    
	render(){
		return (
			<h2>{this.state.date.toLocaleTimeString()}</h2>
		);
	}
}

父组件的状态传递到子组件的属性中

class Content extends React.Component {
    //在渲染前调用,在客户端也在服务端
  	componentWillMount() {
      	console.log('Component WILL MOUNT!')
  	}
    //在第一次渲染后调用,只在客户端
  	componentDidMount() {
       console.log('Component DID MOUNT!')
  	}
    //在组件接收到一个新的 prop (更新后)时被调用
 	componentWillReceiveProps(newProps) {
        console.log('Component WILL RECEIVE PROPS!')
  	}
    //在组件接收到新的props或者state时被调用
  	shouldComponentUpdate(newProps, newState) {
        return true;
  	}
    //在组件接收到新的props或者state但还没有render时被调用
  	componentWillUpdate(nextProps, nextState) {
        console.log('Component WILL UPDATE!');
  	}
    //在组件完成更新后立即调用
  	componentDidUpdate(prevProps, prevState) {
        console.log('Component DID UPDATE!')
  	}
    //在组件从 DOM 中移除的时候立刻被调用
  	componentWillUnmount() {
         console.log('Component WILL UNMOUNT!')
 	}
  
  	render() {
  		return (
  			<div>
  				<h3>{this.props.myNumber}</h3>
  			</div>
  		);
  	}
}

class MyApp extends React.Component {
	constructor(props) {
		super(props);
        //声明状态
		this.state = {
			data: 0,
            isRender: true
		};
		
		this.setNewNumber = this.setNewNumber.bind(this);
        this.deleteDOM = this.deleteDOM.bind(this);
	}
	//改变状态值并传递到子组件
	setNewNumber() {
		this.setState({data: this.state.data + 1});
	}
    //删除子组件
    deleteDOM() {
        this.setState({isRender: false})
    }
	
	render() {
		return (
			<div>
				<button onClick={this.setNewNumber}>点我改变状态</button>
                <button onClick={this.deleteDOM}>点我删除子组件</button>
                { this.state.isRender ? <Content myNumber={this.state.data} /> : null }
			</div>
		);
	}
}

ReactDOM.render(
	<div>
		<MyApp />
	</div>,
	document.getElementById('root')
);
import React, { Component } from 'react'
export default class Box extends Component {
  constructor() {
    super()
    this.state = {
      count: 2,
      token: "abcdqwe"
    }
    this.increment1 = function () {
      this.setState({ count: this.state.count + 1 })
    }
    this.changetoken = function () {
      this.setState({ token: "abcdqwe2" })
    }
    console.log("constructor")
  }
  render() {
    console.log("render--box")
    return (
      <div>
        <p>{this.state.count}</p>
        <button onClick={this.increment1.bind(this)}>count++</button>
        <button onClick={this.changetoken.bind(this)}>change_token</button>
      </div>
    )
  }
  componentWillMount() {
    console.log("componentWillMount")
  }
  componentWillReceiveProps() {
    console.log("componentWillReceiveProps")
  }
  componentDidMount() {
    console.log("componentDidMount")
  }
  componentWillUpdate() {
    console.log("componentWillUpdate")
  }
  shouldComponentUpdate() {
    console.log("shouldComponentUpdate", arguments)
    //只有传入的有count而是是新值 才更新
    if (arguments[1].count && arguments[1].count != this.state.count) { return true }
    else { return false }
  }
  componentDidUpdate() {
    console.log("componentDidUpdate")
  }
  componentWillUnmount() {
    console.log("componentWillUnmount")
  }
}

 3、生命周期钩子——网络请求

componentDidMount

import React, { Component } from 'react'
export default class Box2 extends Component {
    state={
        arr:[]
    }
  render() {
    return (
      <div>
        <h1>box2</h1>
        {
            this.state.arr.map(el=><div>{el.title}----{el.age}</div>)
        }
      </div>
    )
  }
  componentDidMount(){
    fetch("http://192.168.6.78:7001/test").then(res=>res.json())
    .then(data=>{
        console.log(data)
        this.state.arr=data
        this.setState(this.state)
    })
  }
}

  • 作者:爱喝牛奶~
  • 原文链接:https://blog.csdn.net/qq_52301431/article/details/127275659
    更新时间:2023年1月10日07:57:29 ,共 10798 字。