typescript 从子对象内部引用对象的父类的属性

cunj1qz1  于 2023-05-19  发布在  TypeScript
关注(0)|答案(2)|浏览(314)

假设我在一个Angular组件中有四个选项卡要显示,每个选项卡都有自己的显示规则。这里有一个非常抽象的情况描述。

export class View {
  foo: true;
  bar: false;
  tabs: {
    'A': { order: 1, get isVisible() { return this.foo; } },
    'B': { order: 2, get isVisible() { return !this.bar; } },
    'C': { order: 3, get isVisible() { return this.foo && this.bar; } },
    'D': { order: 4, get isVisible() { return !this.foo || this.bar; } }
  };
};

这不起作用,因为this引用tabs对象,而不是包含它的View对象。但是显示各个选项卡的条件取决于View对象的属性。
我认为这是一种更好、更易于维护的方式来组织我的选项卡,而不是以这种方式直接在视图中定义属性:

export class View {
  foo: true;
  bar: false;
  get isTabAVisible() { return this.foo; }
  get isTabBVisible() { return !this.bar; }
  // etc.

有没有什么方法可以组织这些事情来得到我想要的结果?

balp4ylt

balp4ylt1#

任何时候,当你遇到自然方法不适合编程范式的情况时,是时候重新评估你是否使用了正确的方法(要么方法需要改变以适应范式,要么你需要选择一个与你的方法一起工作的范式)。这不是更好吗:

type TabState = {
  foo: boolean
  bar: boolean
}

const state: TabState = {
  foo: true,
  bar: false,
}

enum TabOrder {
  A,
  B,
  C,
  D,
}

type Tab = {
  order: TabOrder
}

const isVisible = ({ foo, bar }: TabState, tab: Tab): boolean => {
  switch (tab.order) {
    case TabOrder.A: return foo;
    case TabOrder.B: return bar;
    case TabOrder.C: return foo && bar;
    case TabOrder.D: return !foo || bar;
  }
}

Playground
这更容易测试(纯函数,只有它的参数),良好的类型,更容易调试,等等。我知道人们普遍认为OO非常适合UI工作,但这并不意味着人们普遍认为OO是正确的。请注意,如果你被框架或现有的代码库锁定在OO中,你总是可以让它成为类的静态方法。

pqwbnv8z

pqwbnv8z2#

你从定义一个类开始,然后切换到一个对象文字的语法。除了代码无效之外,我认为混淆也是问题的一部分--类不是对象,它是一组创建对象的指令。
如果我们首先修复第一个代码片段的语法,它看起来像这样:

export class View {
    foo = true
    bar = false
    tabs = {
      'A': { order: 1, get isVisible() { return this.foo; } },
      'B': { order: 2, get isVisible() { return !this.bar; } },
      'C': { order: 3, get isVisible() { return this.foo && this.bar; } },
      'D': { order: 4, get isVisible() { return !this.foo || this.bar; } }
    }
  };

在这样做之后,我们可以切换到使用显式构造函数来获取对正在构造的对象的引用,并在构造的方法中使用它:

export class View {
    foo = true
    bar = false
    tabs

    constructor() {
      const _this = this;
      this.tabs = {
        'A': { order: 1, get isVisible() { return _this.foo; } },
        'B': { order: 2, get isVisible() { return !_this.bar; } },
        'C': { order: 3, get isVisible() { return _this.foo && _this.bar; } },
        'D': { order: 4, get isVisible() { return !_this.foo || _this.bar; } }
      }
    }
  };

new View()创建对象示例时,在tabs字段下创建的方法将引用新对象的属性。

相关问题