背景
最近做项目时需要为折线图(angular 中使用 echarts 画的图)上的点设置更加个性化的显示和操作:
- 不同数值区间的点以不同颜色显示。
- 点击图上的点后会执行自定义的操作。
查看官方文档后发现,这其实并不困难。因为 echatrs 支持以方法的返回值作为图表中某个属性的值,也提供了接口以监测点击事件,可以在其回调函数中设置点击后的自定义操作。
echarts 官方文档点击这里。
于是对于点的颜色显示问题就有了这样的代码:
inputWarningValue: number = 1000;
lineChartOption = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
itemStyle: {
normal: {
color: function (params: { value: any[]; }) {
const yValue = params.value[1];
if (yValue > this.inputWarningValue) {
return '#ff0031'; // 红色
} else {
return '#048ABF'; // 蓝色
}
}
}
},
lineStyle: {color: '#0367A6'},
}]
} as EChartsOption;
这么写会报错:
但是将函数的写法由 function () {}
改为箭头函数 () => {}
就不会报错了。像这样:
...
itemStyle: {
normal: {
color: (params: { value: any[]; }) => {
const yValue = params.value[1];
if (yValue > this.inputWarningValue) {
return '#ff0031'; // 红色
} else {
return '#048ABF'; // 蓝色
}
}
}
},
...
对于点击后的自定义操作我是这么写的:
constructor(private router: Router,
private route: ActivatedRoute) {
}
ngOnInit() {
this.initCharts();
}
initCharts() {
const ec = echarts as any;
const lineChart = ec.init(document.getElementById('lineChart'));
lineChart.on('click', function () {
console.log('item click');
// 点击某个点后跳转路由
this.router.navigate(['any-url'], {relativeTo: this.route}).then();
})
lineChart.setOption(this.lineChartOption);
}
这样也会报错:
后来尝试发现,除了改变函数的写法外,也还可以用注入静态变量的方式解决的这个问题:
private static routerRef: Router
private static routeRef: ActivatedRoute
constructor(private router: Router,
private route: ActivatedRoute) {
Dec1209Component.routerRef = router;
Dec1209Component.routeRef = route;
}
ngOnInit() {
this.initCharts();
}
initCharts() {
const ec = echarts as any;
const lineChart = ec.init(document.getElementById('lineChart'));
lineChart.on('click', function () {
console.log('item click');
// 点击某个点后跳转路由
Dec1209Component.routerRef.navigate(['any-url'], {relativeTo: Dec1209Component.routeRef}).then();
})
lineChart.setOption(this.lineChartOption);
}
分析之后可以发现,上述两个情形,本质上其实是相同的问题:在不同情况下,this
的指向其实是不一样的。
不同情况下 this
的指向
结果集与情况分类
首先,我们对于 this
指向的结果集需要有个大致的概念。
我们一般接触的 this
指向有两个可能的结果:当前对象、当前对象的上下文。
其次我们都知道,this
的使用场景通常都在某个函数中,所以这里所说的不同情况其实指的也就是函数的不同情况。
函数在写法上我们最常见有两种:
- 普通写法:
function() {}
。一般在类中我们都会这么定义函数。 - 箭头函数:
() => {}
。一般在回调中我们会用这种写法。
函数的调用方式也可以分类:
- 对象方法调用:
object.function()
。最常见的调用方式。 - 将方法赋值给变量后再调用:
const func = object.function; func()
。不太常见。
我们姑且可以根据上述分类来分别测试 this
的指向。
测试及结果
angular 中我们可以在某个组件中准备这样的测试代码:
export class Dec1209Component implements OnInit {
value: string = 'getFromContext';
ngOnInit() {
const object = {
value: "getFromSelfObj",
getValueByArrow: () => {
return this.value;
},
getValueByGeneral() {
return this.value;
},
};
console.log('箭头函数 + 对象方法调用', object.getValueByArrow());
const arrowFunc = object.getValueByArrow;
console.log('箭头函数 + 赋值变量调用', arrowFunc());
console.log('普通写法 + 对象方法调用', object.getValueByGeneral());
const generalFunc = object.getValueByGeneral;
console.log('普通写法 + 赋值变量调用', generalFunc());
}
}
运行后得到以下结果:
总结
一、函数写法为箭头函数 function: () => {}
时
不管是对象方法调用,还是赋值变量调用,this 指向当前定义函数时所在的上下文。
二、函数写法为普通写法 function() {}
时
1.对象方法调用时,this 指向的就是当前执行函数时所在的上下文,通常就是当前对象。
2.赋值变量调用时,this 似乎既不指向当前对象,也不指向当前对象的上下文。(待深究)
希望这篇文章对你有帮助。
参考资料
https://zhuanlan.zhihu.com/p/104565681
https://zhongsp.gitbooks.io/typescript-handbook/content/doc/w...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。