2022即将到来,前端发展非常迅速,现在的前端已经不再是写写简单的页面了,伴随着web大前端,工程化越来越火,也出现了很多框架。很多公司也不单单是使用单一的框架了,作为前端开发国内最火的两大框架,都是必须要掌握的。所以,我决定在这疫情肆虐的年底把React学习一下,也为自己将来找工作多一分竞争力...
学习阶段,如有不对之处,欢迎评论区留言,我及时更正
本文已连载,其它章节传送门⬇️
事件处理
React中事件处理必须采用小驼峰命名方式,且阻止默认行为必须显示的调用e.preventDefault()
💡问题:React中绑定事件this指向问题
import React from 'react'
import ReactDoM from 'react-dom'
class Count extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
handleClick() {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<div>
<h2>当前求和为{this.state.count}</h2>
<button onClick={this.handleClick}>点击</button>
</div>
)
}
}
ReactDoM.render(<Count />, document.querySelector("#root"))
当我们点击执行handleClick
的时候报错,不能读取undefined的setState属性,也就是this 是undefined,找不到this了,接下来我直接说明原因:
-
函数调用模式 this默认指向window,但在模块化中默认开启了严格模式,this指向undefined
-
我们知道render函数中this没有问题,原因是render函数是react的实例帮我们调的,构造函数的实例调的,this就指向实例本身
-
我们注册的事件并不是react调的 是当我们触发了点击事件等等,作为回调传给onClick事件的,也就是函数执行的结果赋值给了onClick,所以这里的this指向了undefined,undefined身上自然没有setState方法
解决方案
第一种:bind改变this指向
class Count extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
// this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<div>
<h2>当前求和为{this.state.count}</h2>
<button onClick={this.handleClick.bind(this)}>点击</button>
</div>
)
}
}
bind写在jsx中和写在constructor中一样,render函数是实例调用方法,this指向类,constructor也一样
第二种:箭头函数
class Count extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
handleClick = () => {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<div>
<h2>当前求和为{this.state.count}</h2>
<button onClick={this.handleClick}>点击</button>
</div>
)
}
}
箭头函数是没有this的,默认与父级保持一致,所以指向了实例
传参
💡 如果我们需要传参,会发生什么呢?
class Count extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
handleClick = (num) => {
console.log(num)
}
render() {
return (
<div>
<h2>当前求和为{this.state.count}</h2>
<button onClick={this.handleClick(2)}>点击</button>
</div>
)
}
}
刷新浏览器,我还没有点击就已经触发了函数执行,并且当我再次点击的时候不会再执行了,因为我们在模板中直接调用了函数,函数执行过了已经
回调传参
<button onClick={() => { this.handleClick(2) }}>点击</button>
写成回调函数的形式,当我们触发onClick事件,执行的是外层的箭头函数,箭头函数执行的结果是执行了handleClick ,而如果是直接执行,那么一上来就调用了一次直接,这种方法包一层箭头函数,只有当我点击的时候里面的箭头函数才会执行,其实也就是柯里化函数。