英文:
Referencing properties of an object's parent class from inside the child object
问题
It seems like you want to organize your Angular component to determine the visibility of tabs based on properties of the View object. To achieve this, you can define a getter for each tab's visibility within the component. Here's a translation of your code:
假设我有四个选项卡要在Angular组件中显示,每个选项卡都有自己的显示规则。以下是这种情况的一个非常抽象的描述。
这不起作用,因为“this”引用“tabs”对象,而不是包含它的View对象。但是,显示各个选项卡的标准取决于View对象的属性。
我发现这比以这种方式直接在View内部定义属性更好且更易维护:
有没有办法组织这个以获得我想要的结果?
If you have any specific questions or need further assistance with this code, please feel free to ask.
英文:
Suppose I have four tabs to display in an Angular component, each with its own rule for whether to display it. Here's a very abstract depiction of the situation.
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 doesn't work because this
refers to the tabs
object, not to the View object that contains it. But the criteria for display the respective tabs depend on properties of the View object.
I figured this is a better and more maintainable way to organize my tabs than defining the properties directly inside the View in this manner:
export class View {
foo: true;
bar: false;
get isTabAVisible() { return this.foo; }
get isTabBVisible() { return !this.bar; }
// etc.
Is there a way to organize this to get the outcome I'm looking for?
答案1
得分: 1
以下是您要翻译的内容:
"Any time you come across a situation where the natural approach doesn't fit the programming paradigm, it's time to re-evaluate whether you are using the correct one (either the approach needs to change to fit the paradigm, or you need to pick a paradigm that works with your approach). Isn't this arguably better:
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;
}
}
This is easier to test (a pure function of only its arguments), well-typed, easier to debug, etc., etc. I know the received wisdom is that OO is well-suited for UI work, that doesn't mean the received wisdom is correct. Note that if you're locked into OO by a framework or the existing codebase, you can always make it a static method of the class."
英文:
Any time you come across a situation where the natural approach doesn't fit the programming paradigm, it's time to re-evaluate whether you are using the correct one (either the approach needs to change to fit the paradigm, or the you need to pick a paradigm that works with your approach). Isn't this arguably better:
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;
}
}
This is easier to test (pure function of only it's arguments), well-typed, easier to debug, etc. etc. I know the received wisdom is that OO is well-suited for UI work, that doesn't mean the received wisdom is correct. Note that if you're locked in to OO by a framework or the existing codebase you can always make it a static method of the class.
答案2
得分: 0
你首先通过定义一个类开始,但后来切换到对象字面量的语法。除了代码无效之外,我认为困惑也是问题的一部分 - 类不是对象,它是一组创建对象的指令。
如果我们首先修复第一个片段的语法,它将如下所示:
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
字段下创建引用新对象属性的方法。
英文:
You're starting off by defining a class, but then switches to a syntax of an object literal. Beside the code being invalid, I think that confusion is part of the problem - a class isn't an object, it's a set of instructions for creating an object.
If we first fix the syntax of your first snippet, it would look like this:
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; } }
}
};
After doing that, we can switch to use an explicit constructor in order to get a reference to the object being constructed, and use it inside the constructed methods:
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; } }
}
}
};
When an object instance would be created by new View()
, the methods that would be created under the tabs
field would reference the properties of the new object.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论