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

首页 / 文章分类 / 正文

目录

一、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 (             
{/* 1、受控组件 */} {/* 2、非受控组件 */} {/* 如果上没有onChange事件,输入框不能输入,value会一直是this.state.value */}
) } } 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 ( 			

input_checked 受控组件



{this.state.gender}
); } } ReactDOM.render( , 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 (       
) } }

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 (       
) } }

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 (       
) } }

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 (       
) } }

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 (             

{this.state.msg}

) } }

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 ( 			

{this.state.value}

//方法6:因为react中函数不能写小括号,所以自己设计,去实现有小括号,传参
); } }

(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 ( 			
); } }

解决方法:

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

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

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

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

  //将changeData处理为有this 

{e=>this.changeData.call(id,event)}

//又想传参又要处理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 (       
{/* */}

{this.state.msg}

{ this.state.arr.map(el => (

{el.title}

)) }
) } }

二、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 ( 			

{this.state.date.toLocaleTimeString()}

); } }

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

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 (   			

{this.props.myNumber}

); } } 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 (
{ this.state.isRender ? : null }
); } } ReactDOM.render(
, 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 (       

{this.state.count}

) } 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 (       

box2

{ this.state.arr.map(el=>
{el.title}----{el.age}
) }
) } 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) }) } }