React组件事件绑定
关于this
一个问题
假设有这样一个问题,求输出语句的打印
var obj = {
fn:function(){
console.log(this)
}
}
var outFn = obj.fn
obj.fn() //this为obj
outFn() //this为window
为什么会出现这样的状况?
函数调用
函数调用有三种方式(暂时不讨论apply)
fn(p1,p2)
obj.fn(p1,p2)
obj.call(context,p1,p2)
其中第三种方式才是真正的函数调用方式
在第三种方式中 context是指this的指向
前两种调用方式只是语法糖 所以他们只是第三种方式的简写
那么我们就可以翻译前两种写法
fn.call(null,p1,p2)
obj.fn(obj,p1,p2)
由于浏览器默认当context为null/undefined时,this会指向window 所以fn()的this为window
代码转换
还是上述题目
var obj = {
fn:function(){
console.log(this)
}
}
var outFn = obj.fn
obj.fn()
outFn()
把这个题目的所有函数调用用call代替
var obj = {
fn:function(){
console.log(this)
}
}
var outFn = obj.fn
obj.fn.call(obj) //this就是obj
outFn.call(null) //因为context为null,所以this为window
一些题目
var a = {
name:'里面的name',
sayName:function(){
console.log('name:',this.name);
}
}
var name = '外面的name'
function sayName(){
var s = a.sayName;
s();
a.sayName();
(a.sayName)();
(b = a.sayName)();
}
sayName()
尝试使用代码翻译
var a = {
name:'里面的name',
sayName:function(){
console.log('name:',this.name);
}
}
var name = '外面的name'
function sayName(){
var s = a.sayName();
s.call(null);
a.sayName(a);
(a.sayName).call(a);
b.call(null);
}
sayName()
var length = 10
function fn(){
console.log(this.length)
}
var obj = {
length:5,
method:function(){
fn()
arguments[0]()
}
}
obj.method(fn,1)
尝试使用代码转换
var length = 10
function fn(){
console.log(this.length)
}
var obj = {
length:5,
method:function(){
fn.call(null) // this.length === 10
// arguments.0是错误语法 这里只是为了方便理解
arguments.0.call(argument) // this.length === argument.length === 2
}
}
obj.method.call(obj,fn,1) //this === obj && argument === [fn,1]
箭头函数的this
箭头函数本身是不支持this和arguments的
如果看到箭头函数有this 就把箭头函数里的this当作外面的this
例如
class A{
constructor(){
this.fn = ()=>{console.log(this)}
}
}
var a = new A()
a.fn()
var b = a.fn
b()
事件绑定的this
btn.addEventListener('click',function handle(){
console.log(this)
})
上述代码可以被翻译为
btn.onclick = function handle(){
console.log(this)
}
用call做代码翻译
btn.onclick.call(btn) //this === btn
React事件绑定的方法
还是+1的例子 我们要给button绑定click事件,使得能够实现+1
class A extends React.Component{
constructor(){
super()
this.state = {
n:0
}
}
addN(){
this.setState({n:this.state.n+1})
}
render(){
return (
<div>
{n}<button onClick=·····>n+1button>div>
)
}
}
问题是❓:省略号内的内容如何写
this.addN()}>n+1</button>
- 这种方法是一种万无一失的方法
this.addN}>n+1</button>
- 这种方法会使得addN内部的this变成window
- 当事件被点击的时候,会调用button.onClick.call(null)
- 所以this会变成window
this.addN.bind(this)}>n+1</button>
- 通过强制绑定this.不会使得addN内部的this变成window
class A extends React.Component{
constructor(){
super()
···
this._addN = ()=> this.addN()
}
}
this._addN}>n+1</button>
- 由于4还需要重新起名 所以我们做一个改进
class A extends React.Component{
constructor(){
super()
···
this.addN = ()=> this.setState({n:this.state.n+1})
}
}
this.addN}>n+1</button>
- 最终答案
一个语法糖 使得我们不需要把事件处理函数写在构造函数内
class A extends React.Component{
constructor(){
super()
···
}
addN = ()=> this.setState({n:this.state.n+1})
}
this.addN}>n+1</button>
mindSet
相比于Vue,React令人感觉对于新手更有劝退性。React能把人逼疯,但是疯过之后会让人涅槃重生,加油 继续React之旅
Goodbye