Angular组件中实现标签页显示规则集中配置时,如何引用父类实例的属性
这个问题我之前也碰到过,把标签的显示规则集中在一个对象里维护,确实比零散定义一堆isTabXVisible的getter要整洁得多。你遇到的核心问题就是对象里的getter函数中,this指向的是当前的tab对象而非组件类实例,所以没法访问foo、bar这些组件属性。下面给你几个实用的解决办法:
方法一:用箭头函数替代getter
箭头函数的this是词法作用域绑定的,也就是它会捕获定义时所在上下文的this(也就是组件类实例),刚好能解决你的问题。只需要把每个tab的isVisible getter改成箭头函数即可:
export class View { foo = true; bar = false; tabs = { 'A': { order: 1, isVisible: () => this.foo }, 'B': { order: 2, isVisible: () => !this.bar }, 'C': { order: 3, isVisible: () => this.foo && this.bar }, 'D': { order: 4, isVisible: () => !this.foo || this.bar } }; }
使用的时候注意要调用这个函数:tab.isVisible(),因为它不再是getter属性了。这种方式最简洁,适合不需要getter语法的场景。
方法二:在构造函数中用变量保存组件实例
如果你想保留getter的语法(也就是不用加括号就能访问tab.isVisible),可以在构造函数里用一个变量先保存组件的this,然后在tab的getter里引用这个变量:
export class View { foo = true; bar = false; tabs: Record<string, { order: number; get isVisible(): boolean }>; constructor() { // 保存组件实例的引用 const component = this; this.tabs = { 'A': { order: 1, get isVisible() { return component.foo; } }, 'B': { order: 2, get isVisible() { return !component.bar; } }, 'C': { order: 3, get isVisible() { return component.foo && component.bar; } }, 'D': { order: 4, get isVisible() { return !component.foo || component.bar; } } }; } }
这样tab的getter里引用的component就是组件类实例,自然能访问到foo和bar属性,而且使用的时候还是tab.isVisible,和你原来的写法体验一致。
方法三:初始化时绑定组件实例到方法
如果你的tabs对象需要提前定义(比如在类的顶层而非构造函数里),还可以在组件初始化阶段(比如ngOnInit),用bind把组件实例绑定到每个tab的isVisible方法上:
import { OnInit } from '@angular/core'; export class View implements OnInit { foo = true; bar = false; tabs = { 'A': { order: 1, isVisible() { return this.foo; } }, 'B': { order: 2, isVisible() { return !this.bar; } }, 'C': { order: 3, isVisible() { return this.foo && this.bar; } }, 'D': { order: 4, isVisible() { return !this.foo || this.bar; } } }; ngOnInit() { // 遍历所有tab,把isVisible方法的this绑定到组件实例 Object.values(this.tabs).forEach(tab => { tab.isVisible = tab.isVisible.bind(this); }); } }
这种方式适合tabs结构比较固定,需要提前声明的场景,绑定之后调用tab.isVisible()就能正确访问组件的属性了。
这几种方法都能实现你想要的集中管理标签显示规则的需求,你可以根据自己的使用习惯和场景选择最合适的一种~
备注:内容来源于stack exchange,提问作者Green Grasso Holm

