深入理解 React 中的上下文 this
写在前面
JavaScript中的作用域scope 和上下文 context 是这门语言的独到之处,每个函数有不同的变量上下文和作用域。这些概念是JavaScript中一些强大的设计模式的后盾。在ES5规范里,我们可以遵循一个原则——每个function内的上下文this指向该function的调用方。比如:
var Module = { name: 'Jafeney', first: function() { console.log(this); // this对象指向调用该方法的Module对象 var second = (function() { console.log(this) // 由于变量提升,this对象指向Window对象 })() }, init: function() { this.first() }}Module.init()
:''}{item.title}]
})
}
_renderBody() { let _renderRow = this.renderRow; return this.state.dataSource.map((item) => { return _renderRow && _renderRow(item) })}render() { let state = this.state; return ( {this._renderHead()} {this._renderBody()} )}
}
export default Table
Component是React内的一个基类,用于继承和创建React自定义组件。ES6规范下的面向对象实现起来非常精简,class关键字 可以快速创建一个类,而Component类内的所有属性和方法均可以通过this访问。换而言之,在Component内的任意方法内,可以通过this.xxx的方式调用该Component的其他属性和方法。接着分析上面的代码,寥寥几行实现的是对一个Table组件的封装,借鉴了ReactNative组件的设计思路,通过外部传递dataSource(数据源)、columns(表格的表头项)、renderRow(当行渲染的模板函数)来完成一个Table的构建,支持全选和取消全选的功能、允许外部传递className和style对象来修改样式。从这个例子我们可以发现:只要不采用function定义函数,Component所有方法内部的this对象始终指向该类自身。### container 调用 component 时传递的 this还是继续上面的例子,下面在一个做为Demo的container里调用之前 的Table。
import Table from '../../components/Views/Table/'
接着编写renderRow函数并传递给Table组件
_renderRow(row) {
// ------------ 注意:这里对callback函数的写法 -----------
let onEdit = (x)=> {
console.log(x+x)
}, onDelete = (x)=> {
console.log(x*x)
}
// ---------------------------------------------------
return (
{row.key} {row.name} {row.age} {row.birthday} {row.job} {row.address} onEdit(row.key)} text="编辑" /> onDelete(row.key)} text="删除" />)
}
//... 省略一大堆代码
render() {
let dataSource = [{
key: '1',
name: '胡彦斌',
age: 32,
birthday: '2016-12-29',
job: '前端工程师',
address: '西湖区湖底公园1号'
}, {
key: '2',
name: '胡彦祖',
age: 42,
birthday: '2016-12-29',
job: '前端工程师',
address: '西湖区湖底公园1号'
}],columns = [{
title: '编号',
dataIndex: 'key',
key: 'key',
},{
title: '姓名',
dataIndex: 'name',
key: 'name',
}, {
title: '年龄',
dataIndex: 'age',
key: 'age',
}, {
title: '生日',
dataIndex: 'birthday',
key: 'birthday',
}, {
title: '职务',
dataIndex: 'job',
key: 'job',
},{
title: '住址',
dataIndex: 'address',
key: 'address',
}, {
title: '操作',
dataIndex: 'operate',
key: 'operate',
}];
return (
);
}
显示效果如下:分析上面的代码,有几处容易出错的地方:1. _renderRow 作为component的方法来定义,然后在对应的render函数内通过this来调用。很重要的一点,这里this._renderRow作为的是函数名方式传递。1. _renderRow 内部Button组件的callback是按钮点击后触发的回调,也是一个函数,但是这个函数没有像上面一样放在component的方法里定义,而是作为一个变量定义并通过匿名函数的方式传递给子组件:
let onEdit = (x)=> {
console.log(x+x)
}
// .....
callback={()=>onEdit(row.key)}
这样就避开了使用this时上下文变化的问题。这一点是很讲究的,如果沿用上面的写法很容易这样写:
onEdit(x) {
console.log(x+x)
}
// ...
callback={()=>this.onEdit(row.key)}
但是很遗憾,这样写this传递到子组件后会变成undefined,从而报错。1. 父组件如要调用子组件的方法,有两种方式:第一种 通过匿名函数的方式
callback = {()=>this.modalShow()}
1. 第二种 使用 bind
callback = {this.modalShow.bind(this)}
注意:如果要绑定的函数需要传参数,可以这么写: xxx.bind(this,arg1,arg2...)## 参考《ECMAScript 6 入门》@欢迎关注我的 github 和 个人博客 -Jafeney#JavaScript、react.js、es2015#
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!