目录
一、React的事件
1、react使用的是合成事件而非原生的DOM事件。在React中给元素添加事件类似于行间事件
(1)行间事件: 事件名称(‘onclick等’)纯小写,事件接收的是字符串
<button onclick='事件处理函数名'>提交</button>
(2)React类似于行间事件:事件名称采用驼峰命名法,可以通过JSX插值表达式放入函数
<button onClick={this.clickHandler}>点击</button>
2、在React中添加事件时要注意的问题
(1)事件处理函数是没有绑定this:即在事件处理函数中this为undefined
(2)若在事件处理函数中要使用this,可以将该事件处理函数变成箭头函数,或者通过bind绑定this
(3)获取事件源:
clickHandler=(e)=>{
console.log(e.target) //输出事件源
}
(4)在React中阻止默认事件不能用return false,必须使用event.preventDefault()
e.preventDefault()
二、表单的使用
1、将组件的状态(state)与表单的状态进行绑定:当组件的state发生改变时,修改表单的状态,或者表单的状态被改变时通过setState
修改组件的状态,这样就形成了组件对表单控件的控制—受控组件
(1)输入类型的表单控件:控制value的值
💥举例:
FormComponent.jsx代码段:
import React,{Component} from "react";
class FormComponent extends Component{
constructor(props) {
super(props);
this.state = {
val:'西安'
}
}
render() {
let {val} = this.state
return (
<>
<input value={val} type='text' onChange={(e =>{
this.setState({
val:e.target.value //将表单控件的值赋给组件的状态属性
})
})} />
<br/><br/>
<p>{val}</p>
</>
)
}
}
export default FormComponent;
(2)单选框和复选框控制的是checked属性
受控组件:实现组件的状态和表单控件状态的同步(间接实现了双向绑定)
非受控组件:组件的状态和表单控件状态不同步(只是表单控件的初值和组件的state一致)。无需添加onChange事件, 对于输入型表单控件使用defaultValue,对于复选框和单选框使用defaultChecked
非受控组件
💥举例:
Student.jsx代码段:
import React from "react";
class Student extends React.Component{
state = {
val:'兵马俑',
checked:false
}
render() {
let { val,checked } = this.state
return(
<>
<input type={'text'} defaultValue={val}/>
<br/><br/>
<input type={'checkbox'} defaultChecked={checked}/>游泳
<br/><br/>
<p>{val}</p>
</>
)
}
}
export default Student;
三、函数组件
函数组件:一个函数就是一个组件(简易组件)。函数的第一个参数是父级组件传过来的props,返回值是该组件要输出的视图
1、在React16.7之前函数组件中不能定义state,也没有生命周期。一般只作为纯粹的展示组件来使用。又称为无状态组件。
2、类组件的缺点:
- (1)关于this的绑定问题
- (2)很多业务逻辑写在生命周期函数
componentDidMount
,这样使组件变得复杂并难以维护
3、React Hooks
React Hooks:React16.8版本中开始使用。本质是一个特殊的函数,提供很多个内置的Hook,来帮助开发者实现很多只能在类组件中使用的功能。
(1)useState
useState :通过该hook,开发者可以在函数组件中使用state
语法:const [state,setState] = useState(initialState)
该方法的第一个参数’initialState’:是state的初始值,该方法返回的是一个数组
该数组的第一个元素(索引为0的元素)是state的具体值
该数组的第二个元素(索引为1的元素)是一个方法,用来更新state
💥举例:
School.jsx代码段:
import React ,{useState} from "react";
function School(){
const [schoolName,setSchoolName] = useState('西安邮电学校')
return(
<>
<p>学校名称:{schoolName}</p>
<button onClick={()=>{
setSchoolName('西安邮电大学')
}}>学校新名称</button>
</>
)
}
export default School;
点击按钮后:
注意的问题:
a、useState的返回setState方法是同类组件的setState,是一个异步方法,需要组件更新后
state的值才能变成新值
b、useState的返回setState方法不能像类组件中的setState方法来更改多个属性的值
c、在函数组件中可以使用useState创建多个state
💥举例:
School.jsx代码段:
import React ,{useState} from "react";
function School(){
const [schoolInfo,setSchoolInfo] = useState({name:'西电',address:'光华路'})
return(
<>
<p>学校名称:{schoolInfo.name}</p>
<p>学校地址:{schoolInfo.address}</p>
<button onClick={()=>{
setSchoolInfo({
//...schoolInfo,
name:'西安电子科技大学',
address: '草堂寺'
//如果只改name的值,而不写address,address的值会变为空;如果想只改name,就需要先利用...schoolInfo解构,这样改就不会影响下面的其他属性了
})
}}>修改对象的值</button>
</>
)
}
export default School;
点击后
(2)useRef
useRef:看成是createRef的Hook版。使用方法:
(1)先将ref存入变量
let el = useref()
(2)再将变量与DOM节点进行绑定,通过Ref的
current
属性来获取节点
<p ref={ el }>web开发</p>
el.current
useRef的作用:
(1)可以绑定DOM组件
(2)可以获取组件渲染之前的数据
💥举例:
RefDemo.jsx代码段:
import React,{useRef} from "react";
function RefDemo(){
let elP = useRef();
return (
<div>
<p ref = { elP }>Web开发</p>
<button onClick={()=>{
console.log(elP.current)
}
}>显示内容</button>
</div>
)
}
export default RefDemo;
App.js中代码段:
import logo from './logo.svg';
import './App.css';
import RefDemo from "./components/RefDemo";
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
</header>
<RefDemo/>
</div>
);
}
export default App;
显示如下:
(3)useEffect
useEffect:在类组件中副作用通常在
componentDidMount
、componentDidUpdate
、componentWillUnMount
生命周期函数中进行处理。在函数组件中useEffect相当于以上三个钩子函数的集合体
包含两个参数:第一参数是执行时的回调函数、第二个参数是依赖参数,并且回调函数还有一个返回参数
(1)依赖参数:是一个数组,数组中存放的是要依赖的依据,当这些数据更新时就会执行回调函数
(2)执行过程:
组件挂载–>执行副作用(回调函数)–>组件更新–>执行清理函数
💥举例:
Course.jsx代码段:
import React, {useState,useEffect} from "react";
function Course(){
const [course,setCourse] = useState('Web高级工程师')
const [num,setNum] = useState(1)
useEffect(()=>{
console.log('组件挂载或更新')
return ()=>{ //返回回调函数
console.log('清理更新之前的一些内容,或检测组件即将卸载')
}
},[num])
return(
<>
<div>
选择课程:
<select
value={ course }
onChange={ ({target})=>{ setCourse(target.value)} }
>
<option>Web全栈工程师</option>
<option>Web高级工程师</option>
<option>Web-UI工程师</option>
</select>
</div>
<div>
购买数量:
<input type={'number'}
value={ num }
min={1}
onChange={({target})=>{ setNum(target.value)}}
/>
</div>
</>
)
}
export default Course;
App.js代码段
import logo from './logo.svg';
import './App.css';
import Course from "./components/Course";
import {useState} from "react";
function App() {
const [show,setShow] = useState(true); //由show决定Course组件是否显示
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
</header>
{ show?<Course/>:''} {/*若show为true则显示Course组件,否则不显示*/}
<br/><br/>
<button onClick={()=>{ setShow(!show)}}>{ show?'隐藏课程':'显示课程'}</button>
</div>
);
}
export default App;
注意:类组件需要通过render(){return()}才能返回渲染 ,而 函数组件直接通过return返回来渲染
4、Hooks的使用规则
(1)只能在函数组件和自定义的Hooks中调用Hooks。类组件和普通函数不能使用Hooks
(2)只能在函数的第一层中调用Hooks。在函数中若使用了流程控制语句(if、for、while),在流程控制语句中不能使用Hooks;若函数中定义了子函数,子函数中也不能使用Hooks。
5、自定义Hooks(示例)
自定义Hooks:在应用中可以将一些需要重复使用的逻辑自定义成Hook
示例:自定义一个Hook,返回一个和滚动条位置实时同步的state
useScrollY.jsx代码段:
import {useState,useEffect} from "react";
function useScrollY(){
let [scrollY,setScrollY] = useState(0)
function scroll(){
//获取window窗口的垂直滚动条
setScrollY(window.scrollY)
}
useEffect(()=>{
window.addEventListener('scroll',scroll); //注册监听
return ()=>{
window.removeEventListener('scroll',scroll) //注销监听
}
},[]);
return scrollY;
}
export default useScrollY;
App.js代码段:
import logo from './logo.svg';
import './App.css';
import useScrollY from "./components/useScrollY";
function App() {
let scrollY = useScrollY();
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
</header>
<div style={{
border:'1px solid #000',
height:'1500px'
}}>
<p style={{position:'fixed',left:0,top:0}}>当前滚动条的位置是:{scrollY}</p>
</div>
</div>
);
}
export default App;