我有一个典型的Glimer“基础”组件:
import Component from '@glimmer/component';
export default class BaseComponent extends Component { ... }
它像往常一样有一个模板,但该组件的实际实现是子组件,它覆盖了一些模板getter和参数,以便它可以处理各种不同的数据类型。
b1a1ab
export default class TypeBComponent extends BaseComponent { ... }
等
我的问题是:如何指定所有子组件都应该使用父类模板,这样就不必为所有子组件复制相同的相当复杂的HTML?从外观上看,组件应该看起来是相同的,因此任何更改都必须在所有子组件类型中复制。因此,多个重复模板并不理想。
在Ember Classic组件中,有layout
和layoutName
属性,因此我只需执行以下操作:
layoutName: 'components/component-name'
在基本组件和所有子组件中,都会自动使用定义的模板。
现在我正在迁移到Glimmer组件,我似乎不知道如何做到这一点。我尝试过:
layout
属性layoutName
属性template
属性- 使用没有模板的子组件,希望它们能够自动回退到父类模板。
似乎唯一有效的方法是按如下方式创建应用程序初始化器:
app.register('template:components/child1-component', app.lookup('template:components/base-component'));
app.register('template:components/child2-component', app.lookup('template:components/base-component'));
但这让我感到很恼火,所以我决定先问一下这里是否有我错过的合适的方法来做这件事?
2条答案
按热度按时间egmofgnx1#
如何为Glimmer Component指定模板?
tl;医生:你应该避免这样。
两个更具体的问题有两个答案:
使用共享行为管理复杂组件的建议方法是什么
通常,您需要重新编写代码以使用组合或服务。
组成
其中BaseBehaviors的模板是:
服务
可以使用创建服务
然后,不是访问
this
上的所有内容,而是访问e1c1d1e中的所有内容忽略所有建议,我在技术上怎么做?
位于同一位置的组件(js+hbs作为单独的文件)在构建时合并到一个文件中,其工作原理如下:
上述js和hbs文件成为以下单个文件:
因此,这意味着您可以在模块级别的任何位置使用
setComponentTemplate
,将模板分配给支持类。为什么与其他方法相比,不建议这样做?
所有这一切都是
layout
及其相关特性没有加入辛烷的主要原因。正式支持的组件继承使人们变得“聪明”
这本身并不是什么问题,而是人们可以用这个工具做什么。糟糕的继承是人们根本不喜欢类的主要原因,也是函数式编程不断增加的原因,这是有道理的!当然,这有点过于纠偏,因为最好的代码在适当的时候同时使用FP和OP,并且不会对这些东西武断。
组件继承更难调试
属于“Foo”但属于“Foo”子类的东西实际上可能不会像“Foo“那样工作,因为在JS中,继承没有严格的规则,所以您可以覆盖getter、方法等,并让它们提供完全不同的行为。
这会让想要调试代码的人感到困惑。
此外,当有人试图进行调试时,他们需要打开更多的文件来理解更大的情况,这会增加认知负荷。
组件继承允许人们忽略边界
这使得单元测试变得更加困难——组件只作为“黑盒”/你看不到的东西进行测试——你测试输入和输出,两者之间没有任何东西。
如果您确实想测试中间层,则需要提取常规函数或服务(或对特定内容进行更多呈现测试)。
1l5u6lss2#
我想说这是合成的经典案例,其中
TypeAComponent
和e1d1e使用BaseComponent
。所以你有了
BaseComponent
和所有的HTML,这基本上就是你的模板。我认为在这里,重要的是要更多地考虑组件以及可能的模板,而不仅仅是完整的组件。因此,让我们称之为TemplateComponent
。所以你有了
TemplateComponent
,它也可以是一个只包含模板的组件。然后,作为TypeAComponent
和TypeBComponent
的模板:这允许您使用getter
propertyThatIsChanged
来覆盖片段。常见行为也可以放在TemplateComponent
上,或者,如果它的公共代码,可能放在只包含共享代码的BaseCodeComponent
中,而我宁愿不这样做。对于要替换的区域,也可以使用Blocks。例如,
TemplateComponent
可以使用has-block
检查:title
是否存在,然后使用该块({{yield to="default"}}
),如果不存在,则只使用e1d 15d1e。因此,唯一明显的缺点是:必须代理所有参数。起初这看起来很难看,但一般来说,我认为组件最好不要有太多的参数。在某种程度上,
options
或data
参数可能更好,也因为在必要时可以用js构建。还应该提到的是,有一个开放的RFC that would address this issue。随着即将到来的证监会,我认为这是一个更加经得起未来考验的整体解决方案。