使用条件逻辑组合 HTML 视图
Posted
技术标签:
【中文标题】使用条件逻辑组合 HTML 视图【英文标题】:Composing an HTML view with conditional logic 【发布时间】:2017-05-21 13:31:57 【问题描述】:在我的多租户应用程序中,我有以下许多实例:
<!-- ko if: tenantA() -->
<div>Tenant One snippet</div>
<!-- /ko -->
<!-- ko if: tenantB() -->
<div>Tenant Two snippet</div>
<!-- /ko -->
<!-- ko if: userTypeA() -->
<div>User type A snippet</div>
<!-- /ko -->
<!-- ko if: userTypeB() -->
<div>User type B snippet</div>
<!-- /ko -->
这是一个过于简单的示例,但您明白了 - 较大视图的许多组件是根据来自不同数据点的业务逻辑组成的。
这样做的好处是我有一个视图并且解决方案的足迹更易于管理,但它有点混乱。有哪些替代模式?
我正在考虑将条件下显示的所有内容拆分为 html 模板并根据 js 视图模型中的逻辑呈现 html,但这会在我的视图模型中引入更多复杂性并混淆我的解决方案足迹(这对我很重要在开发过程中快速导航)。
我正在研究 durandal 和 knockout,但标记为 Aurelia
,因为我将在某个时候迁移并认为这更像是一个模式问题,而不是一个特定的技术问题。
【问题讨论】:
条件是排他性的吗? 【参考方案1】:逻辑模式、软件设计概念
无论您选择使用哪种语言或框架来实现,您都绝对希望根据 components 进行思考。
-
将您的应用程序分成不同的视图(可能每个导航菜单元素都有一个视图)。
根据它们所服务的功能类型进一步细分这些视图中的每一个(根据需要)。我喜欢 Bootstrap 面板帮助您将其可视化的方式。
开发每个组件并为其命名,例如 ContactList、ContactEdit、ContactView 等。为每个组件开发 HTML 视图和 javascript、TypeScript 或其他语言视图模型。请务必使用MVC 逻辑将视图与数据分开,在视图中使用占位符来指示您将在何处填写数据。视图就像模板。
使用您的特定语言或框架将它们链接在一起。
这是关于Component-Based Software Architecture and Design 的精彩教程。
Aurelia 组件逻辑
我目前正在使用Aurelia,既然你提到了,我们将以Aurelia框架为例来说明上述原理。最佳做法是创建组件(用于模块化和重用),然后使用 if.bind
属性将它们包含或不包含在 DOM 中。
例子:
<tenant-one if.bind="tenantA"></tenant-one>
<tenant-two if.bind="tenantB"></tenant-two>
或者仅在视图中显示/隐藏每个组件(但将所有组件包含在 DOM 中),您可以使用 show.bind
而不是 if.bind
,但这似乎对您的用例没有多大意义。
Aurelia 数据绑定
由于我不知道您实际希望在这里显示什么,所以上面的代码是基于您在问题中的代码 sn-p。但是,对于只有数据会更改的类似视图(如模板),您需要将数据从父级绑定到子级,以便正确显示。在 Aurelia 中,这看起来像这样。
例子:
<tenant-view data.bind="tenantData"></tenant-view>
更复杂的例子:
<tenant-view fname.bind="firstName" lname.bind="lastName" data.bind="tenantData"></tenant-view>
在每个示例中,您需要开发 4 个文件。您将需要具有视图和视图模型的主(父)容器。视图模型将负责检索或访问租户信息,然后将其传递给每个子组件。子组件将拥有自己的视图和视图模型。
例如,TenantView 视图(高度简化)可能是这样的:
<template>
<p><strong>Tenant Name: </strong>$fname $lname</p>
<p><strong>Additional Data: </strong>$data</p>
<p if.bind="data.rentDue">Tenant's rent is due!</p>
</template>
然后 TenantView 视图模型(同样,高度简化)可能是这样的:
import bindable, bindingMode from 'aurelia-framework';
export class TenantView
@bindable fname;
@bindable lname;
@bindable data;
创建此组件后,您可以(可选)将其插入到父视图中,如下所示:
<template>
<h1>Contact View</h1>
<h2>$firstName $lastName</h2>
<tenant-view if.bind="cat == 'tenant'" fname.bind="firstName" lname.bind="lastName" data.bind="contactData"></tenant-view>
<phone-numbers data.bind="contactData"></phone-numbers> <!-- another component -->
<page-footer></page-footer> <!-- another component -->
</template>
【讨论】:
这很好,但它是一个特定于技术的解决方案。我想将其抽象为“模式定义”类型的答案,因为我相信这对未来的读者更有价值。您建议将视图组件提取到单独的文件中,然后将视图逻辑留在视图中,对吗? 我唯一的问题是我有数百个这样的实例-视图取决于某些条件。将这些提取到单独的文件中将是一场维护噩梦。 您的视图应该包含适当的逻辑以适应需求的多样性,而不必为每个视图文件提供不同的视图文件。如果目的或结构存在显着差异,您只会显示不同的视图文件。我假设您已经知道如何绑定父子属性。 我更新了我的答案,以提供软件架构和设计中组件逻辑的更广泛视图,以及在 Aurelia 中实现的其他示例。使用组件可以让每个视图根据需要拥有自己的逻辑。 酷 - +1。顺便说一句,您是否会说 Aurelia 处于足够成熟的状态来支持面向消费者的大型应用程序?最后,我检查了它是否处于不断变化的状态,因为约定正在被淘汰(大约 1 年前)。看来我不能再奖励一天了。【参考方案2】:一旦您的应用开始变大,HTML 模板总是会变得凌乱且难以维护。
我建议你将你的 HTML 分解成多个组件,这样会更容易维护,最重要的是你最终会重用所有这些组件。
最好的例子之一是 JSX,它与 React.js 配合得最好,你可以在 JS 中编写 HTML。因此您可以将您的应用程序划分为可维护的组件。试试 JSX,它确实让你作为字体端开发人员的生活更轻松。
【讨论】:
在 Aurelia 中这很容易。最佳实践是创建组件(用于模块化和重用),然后使用if.bind
属性将它们包含或不包含在 DOM 中。以上是关于使用条件逻辑组合 HTML 视图的主要内容,如果未能解决你的问题,请参考以下文章
pandas使用或关系(or)构成组合逻辑筛选dataframe中的满足条件的数据行(use or clause to select dataframe rows)