类中的方法内部的this指向
在用react实现一个点击切换内容小demo时的,发现类中方法内部的this是指向undefined的。
代码如下:
<div id="test"></div>
<script type="text/javascript" src="../JS/react.development.js"></script>
<script type="text/javascript" src="../JS/react-dom.development.js"></script>
<script type="text/javascript" src="../JS/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component{
constructor(props){
super(props)
this.state ={
isHot:false
}
}
render(){
return <h1 onClick={this.weatherClick}>今天天气很{this.state.isHot ? '炎热':'凉爽'}</h1>
}
weatherClick(){
console.log(this);
}
}
ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
点击结果如下:
原因:
①首先,weatherClick
放在那里? –Weather
的原型对象上,供实例使用;
由于weatherClick
在代码中是作为onClick
的回调,所以不是通过实例调用的,是直接调用的,因此并不是这个组件实例了;
②此外,由于类中的方法默认开启了局部的严格模式,因此weatherClick
中的this为undefined
。
验证严格模式会导致函数中的this指向变为undefined
代码如下:
执行结果:
我们发现,在普通函数中,this
的指向是window
;
但是在严格模式下,this
的指向变味了undefined
。
修改方法:在组件的构造器中,使用bind方法 对weatherClick方法进行重包装。
<div id="test"></div>
<script type="text/javascript" src="../JS/react.development.js"></script>
<script type="text/javascript" src="../JS/react-dom.development.js"></script>
<script type="text/javascript" src="../JS/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component{
constructor(props){
super(props)
this.state ={
isHot:false
}
// 解决weatherClick方法中的this指向问题
this.weatherClick = this.weatherClick.bind(this);
}
render(){
return <h1 onClick={this.weatherClick}>今天天气很{this.state.isHot ? '炎热':'凉爽'}</h1>
}
weatherClick(){
// weatherClick放在那里? --Weather的原型对象上,供实例使用
// 由于weatherClick是作为onClick的回调,所以不是通过实例调用的,是直接调用的
// 类中的方法默认开启了局部的严格模式,因此weatherClick中的this为undefined
console.log(this);
}
}
ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
核心:使weatherClick的this重新绑定为这个Weather组件实例
// 解决weatherClick方法中的this指向问题
this.weatherClick = this.weatherClick.bind(this);
执行效果:
完整demo代码:
<div id="test"></div>
<script type="text/javascript" src="../JS/react.development.js"></script>
<script type="text/javascript" src="../JS/react-dom.development.js"></script>
<script type="text/javascript" src="../JS/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component{
constructor(props){
super(props)
this.state ={
isHot:false
}
// 解决weatherClick方法中的this指向问题
this.weatherClick = this.weatherClick.bind(this);
}
render(){
return <h1 onClick={this.weatherClick}>今天天气很{this.state.isHot ? '炎热':'凉爽'}</h1>
}
weatherClick(){
// weatherClick放在那里? --Weather的原型对象上,供实例使用
// 由于weatherClick是作为onClick的回调,所以不是通过实例调用的,是直接调用的
// 类中的方法默认开启了局部的严格模式,因此weatherClick中的this为undefined
console.log(this)
const isHot = this.state.isHot;
this.setState({
isHot:!isHot
})
}
}
ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
思考:当类中的方法特别多的时候,每个方法为了获取这个实例对象,都得在构造器constructor中对其进行this的绑定,岂不是代码篇幅很大?
改进方法:利用箭头函数对类中的this进行绑定。
代码如下:
①将state
从constructor
中提出来,放在class
类定义中
②将class
中定义的方法使用箭头函数进行改写
注:箭头函数的this
指向是取决于箭头函数外层普通函数的this
,若没有普通外层函数的this
,则指向window
。有关于this指向的问题可参考博客点击进入
查看其第一部分即可。
<body>
<div id="test"></div>
<script type="text/javascript" src="../JS/react.development.js"></script>
<script type="text/javascript" src="../JS/react-dom.development.js"></script>
<script type="text/javascript" src="../JS/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Weather extends React.Component{
constructor(props){
super(props)
}
// 初始化状态
state ={
isHot:false,
wind:'微风'
}
render(){
const {isHot,wind}= this.state;
return <h1 onClick={this.weatherClick}>今天天气很{this.state.isHot ? '炎热':'凉爽'},{wind}</h1>
}
// 自定义方法——要用赋值语句的形式+箭头函数
weatherClick=()=>{
const isHot = this.state.isHot;
this.setState({
isHot:!isHot
})
}
}
// 2.渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
</body>
执行结果:
–
注:类中的方法,若不使用赋值语句的形式,直接写成箭头函数,则会报错;
原因:class中的属性定义规则不允许。
ex:
注意事项总结
this
指向问题
- 类里的方法默认开启局部严格模式,因此直接调用类里的方法
this
为undefined
- 当把类里的方法直接绑定给事件时,方法直接调用,
this
为undefined
,不能访问到组件实例 - 因此通过
bind
方法来绑定this
指向
- 事件绑定问题
-
事件名需要写成驼峰形式 例如:
onclick
写成onClick
-
绑定的回调与传统相比,应该是回调本身,而不是回调的执行
<h1 onclick="changeWeather()"></h1>
// JSX方式,传入回调本身即可
<h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}. {wind}</h1>
-
React
对事件进行改写,如:onxxx
改成onXxx
,是为了更好的兼容性 -
React
中的事件通过事件委托,委托给组件最外层的元素,是为了更高效
- 属性更新问题
- 更新
state
需要使用setState
方法 setState
是合并更新,而不是替换更新