想象一个世界,你的智能手机界面能够根据你的情绪自动调整,你的智能家居会根据时间自动调整设置,特别是在危机时刻,你的业务仪表盘会根据需要实时调整,帮助你做出关键决策。这不再是科幻——这是相对论用户界面带来的承诺,是界面设计的下一个发展方向。
今天的用户界面难以跟上我们数字化生活的复杂性。它们在一个动态世界中显得静态,在面对多样的用户需求时显得僵化,并且与它们所服务的复杂业务领域脱节不连。当我们同时使用多种设备,在不同场景间切换,对数字工具的要求越来越高时,很明显,传统的UI设计范式已经到达了极限。
这篇文章追溯了从原子设计的模块化方法开始,到受可塑性用户界面这一通用概念启发的适应性框架的UI设计演变。我们将探讨原则的概念,以及这些原则如何使将高层次概念打包成可重用组件成为可能,从而简化组件代码。我们将介绍从物理中借用的参照框架概念,并探讨这一概念如何革新用户界面中的上下文感知能力。最后,我们将深入探讨相对论式设计这一新兴范式,借鉴爱因斯坦对伽利略相对性的扩展,并讨论这些概念如何解决实际的用户界面挑战。
原子设计:一致性构建模块布拉德·福斯特的《原子设计》通过引入分层组件结构,强调了模块化和可重用性,彻底改变了用户界面设计。该方法将界面拆解为五个层级。
- 原子(Atoms):基本的UI元素,如按钮、输入字段和图标。
- 分子(Molecules):由原子组合而成的简单组件,例如搜索栏(输入字段+按钮)。
- 组织(Organisms):由分子和原子组成的复杂组件,例如头部区域。
- 模板(Templates):页面级布局,将组件布局到网格或结构中。
- 页面(Pages):具体填充了动态填充的内容的模板实例。
原子设计的好处:
- 一致性:确保界面上的设计语言统一。
- 可重用性:组件可以在不同的场景中重复使用,从而减少重复工作。
- 可扩展性:随着系统的扩展,使更新和维护变得更加简单。
- 协作:在设计师和开发人员之间建立共享的术语。
虽然原子设计提供了构建一致和可重复使用的界面的坚实基础,但它主要针对静态布局,并没有天然地考虑到现代动态的用户交互。
超越静态组件的挑战:探索Reactivity随着 web 应用程序的发展,用户期望也随之演变。现代用户界面必须适应用户交互、设备功能以及应用程序状态的变动。在这样的应用中,即使是像按钮这样简单的东西也可能需要:
- 根据用户的权限来调整其外观。
- 适应触摸界面的大小和布局需求。
- 在被按压时变成加载指示器。
原子化设计的局限性——
- 静态性质:原子是在孤立状态下定义的,并且缺乏内在的灵活性。
- 复杂变化:管理组件的多种状态和变体可能导致代码库变得臃肿。
- 上下文无知:组件不会根据用户角色、设备类型或应用状态内在地进行适应。
为了填补这一空白,我们转向了Mouldable UI(可塑界面)这一概念,它提供了一种更灵活且情境感知的界面设计方式。
灵活可变的用户界面:创建灵活适应的用户界面_可塑性用户界面设计_是一种设计范式,强调创建能够适应各种场景和用户需求的用户界面。起源于Smalltalk编程环境中的设计理念,它提倡在软件设计中保持灵活性和适应性。核心思想是创建可以塑形以适应不同场景的界面,就像陶土可以被塑造成各种形状。
可塑性UI的关键概念(基本理解):
- 设计令牌(Design Tokens):原子化的设计信息(例如颜色、字体和大小),可以一致地应用。
- 变体:根据特定条件或上下文渲染的不同版本或状态的UI组件。
- 原则:指导组件如何通过约束和上下文进行适应的规则或指南。
- 约束条件:通常从查询上下文中得出的条件,指导组件适应。
- 可塑性组件(Mouldables):可以使用变体和其他组件的组合来自我塑造的高级组件。
通过形式化适应逻辑,Mouldable UI 使开发人员能够创建了解自身上下文的组件,并且能够根据情况调整自己的组件。这不仅减少了复杂性和冗余,还使得代码库更加易于维护和扩展。
我们的理解和执行为了展示如何在现代UI开发中应用可塑性UI原则,我们将探讨我们对这些概念的理解和实现,使用一个我们称之为Nuxt Gravity的框架。这是我们的可塑性用户界面诠释,专为使用Nuxt.js构建的Vue.js应用设计。
_Nuxt Gravity 是一个目前正在开发中的库。以下示例展示了如何实现一种可塑的用户界面概念。
特性增强变体:提高组件的灵活性实际示例:基于特质和原则的适应性按钮组件
让我们来看一下一个需要在不同场景下灵活变化的Button
组件。
- 加载状态:在操作进行期间,按钮会显示加载指示器。
- 用户角色:管理员会看到额外的样式。
- 设备类型:触屏设备需要更大的触控区域。
在传统组件设计中,我们会向 Button
组件传递多个 props 来处理这些变化情况。
<!-- 使用 props -->
<Button :isLoading="isLoading" :userRole="userRole" :isTouchDevice="isTouchDevice" />
<!-- 这里的 isLoading, userRole 和 isTouchDevice 是通过 Props 传递的属性 -->
这种方法可能会变得很麻烦,特别是当上下文相关的变体数量增多时。此外,其中许多属性并不属于 Button
本身,而是与外部环境相关的。
使用我们版本的可塑性UI界面和Nuxt Gravity实现的方案
这里是我们如何用Trait变体和原则来实现Button
组件的方法。
<!-- Button.vue -->
<template>
<Trait :principle="buttonTraits" v-slot="{ traits }">
<button v-bind="traits">
{{ buttonText }}
</button>
</Trait>
</template>
<script setup>
import { defineProps, computed } from 'vue';
import { unionPrinciple, rule, trait, always } from 'nuxt-gravity';
const props = defineProps({
isLoading: Boolean,
userRole: String,
isTouchDevice: Boolean,
});
// 定义表示高级概念的原则
const loadingRule = rule(
() => props.isLoading,
trait('button.loading', { class: 'btn-loading', disabled: true })
);
const adminRule = rule(
() => props.userRole === 'admin',
trait('button.admin', { class: 'btn-admin' })
);
const touchDeviceRule = rule(
() => props.isTouchDevice,
trait('button.touch', { class: 'btn-touch' })
);
// 将这些原则组合成一个可重用的包
const buttonTraits = unionPrinciple(
loadingRule,
adminRule,
touchDeviceRule,
always(trait('button.default', { class: 'btn-default' }))
);
const buttonText = computed(() => (props.isLoading ? '正在加载...' : '提交'));
</script>
解释:这里没有内容
- 原则作为可重用的包或规则:我们从规则(如
loadingRule
,adminRule
,touchDeviceRule
)定义原则,这些规则封装了相关的标记和约束条件。 - 打包高层次概念:每个原则代表一个高层次概念(如加载状态、用户角色),并且可以在不同的组件间重用(我们稍后会解决引用
props
的问题,因为这具有可移植性限制)。 - 简化组件代码:通过将规则组合成单一原则
buttonTraits
,我们从组件中移除了复杂的非行为代码,使其更简洁且易于维护。 - 特征合并:当满足条件时,来自不同原则的特征会被合并,从而根据上下文灵活适应。
这里的好处很明显:
- 高级概念的复用性:原则可以应用于多个组件,促进一致性并减少重复。
- 简化:组件更关注行为,而非复杂的适应逻辑。
- 可扩展性:可以添加新的原则而无需改动现有组件结构。
- 清晰性:使用这些原则可以让适应逻辑更清晰,更容易理解。
组装变体:根据原则调整内容结构
电子商务产品卡片示例,带组装变体及示例原则
在电商平台应用中,ProductCard
组件可能需要根据产品类型的不同来展示信息。
- 实体商品:显示配送选项和库存情况。
- 数字下载:突出文件大小和格式。
- 服务:强调预约和可用时间。
根据汇编版本和我们的开发原则进行开发
<!-- ProductCard.vue -->
<template>
<Assembly :principle="productTypePrinciple($props)">
<!-- 物理产品 -->
<template #physical>
<div class="product-card physical">
<!-- 显示产品图片、价格、运输选项和库存量 -->
</div>
</template>
<!-- 数字产品 -->
<template #digital>
<div class="product-card digital">
<!-- 显示产品图片、价格、文件大小和格式 -->
</div>
</template>
<!-- 服务 -->
<template #service>
<div class="product-card service">
<!-- 显示服务描述、调度时间和可用性 -->
</div>
</template>
<!-- 默认 -->
<template #default>
<div class="product-card unknown">
<!-- 显示通用产品信息 -->
</div>
</template>
</Assembly>
</template>
<script setup>
import { defineProps } from 'vue';
import { unionPrinciple, rule, designToken, always, defaultToken } from 'nuxt-gravity';
// 定义产品类型的规则
const productTypePrinciple = (props) => {
const physicalProductRule = rule(
() => props.type === 'physical',
designToken('physical')
);
const digitalProductRule = rule(
() => props.type === 'digital',
designToken('digital')
);
const serviceProductRule = rule(
() => props.type === 'service',
designToken('service')
);
// 将这些原则组合成一个可重用的包
return unionPrinciple(
physicalProductRule,
digitalProductRule,
serviceProductRule,
always(defaultToken)
);
};
defineProps({
type: String, // 'physical', 'digital', or 'service'
});
</script>
解释:
- 产品种类的原理:我们定义代表每个产品种类的原理,包含相关的令牌和约束。
- 可重用性和清晰度:原理可以被重用,并使组件的适应性逻辑清晰且易于维护。
- 消除复杂代码:通过使用原理,我们避免在组件中嵌入复杂的非行为性代码,专注于布局和内容的组织。
为了进一步提高我们界面的适应性,我们引入了“参照系”这一术语的概念,该术语来自物理学。在经典力学里,参照系是一组用于测量物体位置和运动的坐标。伽利略最早提出这一概念来解释物理定律在任何惯性参照系中都相同,而爱因斯坦则通过相对论进一步扩展了这一概念,展示了时间和空间的测量相对于观察者的参照系来说是相对的。
在UI设计中使用参照系在UI设计中,参考框架代表了一个组件可用的局部和全局的上下文,使它们能够根据这些信息做出明智的决策,而不仅仅依赖于传递的属性或全局状态。通过采用这个概念,我们可以使组件直接获取相关上下文信息,从而实现更加灵活且情境感知的界面。
参考框架在实际中的运用通过参照系和原则优化特征例子
回到我们的 Button
组件,我们可以更新它以使用参照系,并进一步利用这些原理。不再传递类似 isLoading
、userRole
或 isTouchDevice
这样的 props,而是依赖从模块中导入的可组合查询标识符。
更新实现,包含参照框架和我们的原则和理念:
<!-- Button.vue -->
<template>
<Trait :principle="buttonPrincipleBundle" v-slot="{ traits }">
<button v-bind="traits">
{{ buttonText }}
</button>
</Trait>
</template>
<script setup>
import { computed } from 'vue';
import {
unionPrinciple,
rule,
trait,
always,
query,
some,
useFrame,
} from 'nuxt-gravity';
// 从模块中导入查询标识符
import { isLoadingQuery, isAdminQuery, isTouchDeviceQuery } from 'my-queries';
// 获取框架的引用
const frame = useFrame();
// 使用查询定义约束条件
const isLoading = some(query(isLoadingQuery));
const isAdmin = some(query(isAdminQuery));
const isTouchDevice = some(query(isTouchDeviceQuery));
// 定义代表高层次概念的原则
const loadingPrinciple = rule(
isLoading,
trait('button.loading', { class: 'btn-loading', disabled: true })
);
const adminPrinciple = rule(
isAdmin,
trait('button.admin', { class: 'btn-admin' })
);
const touchDevicePrinciple = rule(
isTouchDevice,
trait('button.touch', { class: 'btn-touch' })
);
// 将这些原则组合成可重用的包
const buttonPrincipleBundle = unionPrinciple(
loadingPrinciple,
adminPrinciple,
touchDevicePrinciple,
always(trait('button.default', { class: 'btn-default' }))
);
const buttonText = computed(() => isLoading(frame) ? '加载中...' : '提交');
</script>
解释:
- 使用从参考框架衍生出的约束原则:我们应用现在使用从参考框架衍生出的约束条件的原则。
- 作为高阶函数的约束:例如
isLoading
这样的约束是评估参考框架内部上下文的函数。 - 组件代码简化:通过将适应逻辑封装在原则和约束中,我们从组件中移除了复杂的代码。
- 全局上下文访问:组件可以在不进行显式的属性传递的情况下访问必要的上下文,使其更具适应性和易于维护。
了解某个函数:
- 约束功能:
some
是一个约束,它将查询函数(frame) => Array
转换为测试函数(frame) => Boolean
,检查是否返回任何结果。 - 用法:通过在查询中使用
some
,我们可以在规则中使用它来判断条件是否得到满足,基于查询是否有任何结果。
就像爱因斯坦在伽利略的工作基础上,进一步发展了相对论来解释光速恒定和时空交织一样,我们可以用相对论的视角来扩展对UI设计的理解。通过使用参照系和相关原则,这样组件就能根据它们在应用程序中的特定环境来感知周围。
介绍UI界面通过使用参照框架,组件现在可以访问应用程序的整个状态空间。这提出了UI 流形的概念,代表了界面中组件之间的结构和关系。
重要概念:
- UI 体系结构 manifold:界面的相互连接的体系,包含所有组件及其关系。
- 局部性与上下文:每个组件都处于特定的上下文中,在这个体系结构中,它们的位置及关系对其有影响。
- 局部决策中的全局考量:组件可以根据局部和全局上下文做出明智的决策,而无需直接管理全局状态的复杂性。
在UI设计中,组件可以具有类似质量和引力的特性,这些特性受到诸如界面流程、视觉突出和上下文相关重要性等因素的影响。
类似的观念 :
- 组件的引力:表示一个组件在一个特定上下文中的重要性或权重。
- 界面的曲率感:具有更高引力的组件如何影响界面的布局和流程走向。
- 最直观路径:通过界面的最直观路径,由组件的排列和重要性形成。
示例:具有可调重力和遵循我们原则的自适应警报组件
让我们考虑一个界面,在该界面中我们需要决定是否在特定位置显示一个紧急提示。我们可以使用一些原则来封装与组件权重相关的逻辑。在这个例子中,我们将假设MouldableGravity
组件(负责计算权重)内部处理了权重的计算,所以我们无需传递任何属性给它。
<!-- AlertComponent.vue -->
<template>
<可塑引力>
<!-- 高引力区域:组件正在UI的焦点位置渲染 -->
<template #high>
<CriticalAlert :message="message" />
</template>
<!-- 中等引力区域:组件重要但不是主要关注点 -->
<template #medium>
<ImportantNotification :message="message" />
</template>
<!-- 低引力区域:组件是UI的一部分 -->
<template #low>
<!-- 选择性地渲染或不渲染更不显眼的组件 -->
<StandardMessage :message="message" />
</template>
</可塑引力>
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
message: {
type: Object,
required: true,
},
});
</script>
- 不需要道具:
MouldableGravity
组件不需要任何 props;它会根据参照系内部计算重力。 - 上下文渲染:根据计算出的重力,相应的槽位(
#high
,#medium
或#low
)会被渲染。 - 简化组件逻辑。:假定
MouldableGravity
负责计算,我们避免在组件中嵌入复杂的逻辑。 - 保持用户关注:这种方法确保在适当情况下,关键警报会突出显示,而不会在不太关键的情况下让用户感到不知所措。
相对性设计通过不仅调整布局以适应不同屏幕尺寸,还根据上下文和用户互动来调整组件的行为和可见性,从而增强了响应式设计的性能。
无需代码的平台,通过将复杂的上下文管理和适应逻辑抽象化,采用相对论设计理念,可以使得无代码平台能够提供更复杂且适应性更强的组件,从而无需用户编写代码。
状态管理与情境感知Relativistic Design 提供了一个框架环境,使组件能够在无需传统状态管理方案的额外开销的情况下访问和响应全局状态而不受限制。这符合现代框架如 React 和 Vue 中的做法,这些框架通过上下文 API 隐式传递状态。
解决真实的UI(用户界面)问题 挑战 1:复杂决策边界在大型应用中,根据多个全局条件确定如何及在哪里渲染组件可能会变得很复杂。
解决方法——
- 作为可重用包的原则:通过将相关的令牌和约束打包成原则,我们简化了复杂的决策逻辑并使其可重用。
- 本地决策点:组件使用参考框架和原则来进行决策,减少了复杂的属性传递过程或全局状态管理的需要。
基于用户的行为习惯和偏好提供个性化的体验。
解决的方法是:
- 上下文查询和原则:组件查询参考框架并应用包含个性化逻辑的原则,从而实现实时适应,无需大量重新配置。
如果动态调整没有高效管理,可能会影响性能表现。
解决方法:
- 高效利用原则:通过仅评估必要约束的原则定义,我们最小化了性能开销。
- 按需渲染:组件根据这些原则进行自适应,避免不必要的重新渲染,从而提高性能。
引入这些概念,比如原则和参照系,以及UI架构,可能会使开发过程变得更为复杂。
回复……
- 学习曲线:尽管一开始存在学习曲线,但从长远来看,这些优点可以抵消初期的复杂性。
- 简化组件代码:这些原则可以帮助去掉组件中的复杂且非行为性的代码,从而使组件更简洁,更易于维护。
访问全局上下文信息并动态调整组件的行为可能导致性能问题。
回复:
- 高效计算:通过优化查询、约束和原则的评估过程,可以最小化性能开销。
- 选择性上下文访问:组件仅通过原则访问必要的上下文,减少不必要的计算。
将上下文管理抽象化可能会让追踪错误更困难,并让理解组件的行为更加困难。
**
- 更强大的调试工具:开发工具可以设计用来可视化参照框架、原则和组件决策,有助于调试。
- 清晰的文档:良好的文档可以减少因原则和模式不清而产生的困惑。
就像爱因斯坦将伽利略的相对性原理扩展,从而革新了我们对物理学的理解一样,我们可以通过采用相对论视角来扩展我们的UI设计方法。通过结合模块化、适应性和情境意识,我们可以扩展我们的UI设计方法,通过原则、参照框架和可组合查询功能,我们可以创建出这样的用户界面:
- 模块化且一致的 (原子设计)
- 灵活且适应情境的 (我们实现的通用可塑性UI概念)
- 整体上适应性强且直观的 (全方位适应设计)
通过将适应性作为首要概念,并将其融入到我们设计的过程中,并利用原则将高层次概念打包成可重用的模块,我们简化了组件代码,使其更易于理解和维护,并消除了复杂的非功能性逻辑。这种方法使我们在各种场景下能够创建真正理解并响应用户和企业多样化需求的接口。
当我们继续深入这些概念的探索时,我们开启了创造更引人入胜、更有效、更用户中心化的界面的新可能性。UI设计的未来不仅仅是让组件看起来美观或在单独使用时表现优秀;而是要创建能够理解和应对复杂性以及不断变化的数字环境的系统。
你准备好深入了解UI设计,迎接相对设计的未来了吗?
资源和更多探索- Nuxt Gravity : 了解更多我们如何在项目中应用可塑性UI原则。(注:Nuxt Gravity 正在开发中,请期待其发布。)
- Smalltalk 中的可塑UI : 探索 Smalltalk 编程环境中可塑UI概念的起源。
- 响应式网页设计 : 探索构建适应不同设备和屏幕大小界面的技术。
- 无代码平台 : 了解如何使用视觉开发工具让UI设计更易于访问。
- UI设计中的原则 : 深入了解原则如何封装高级概念,使组件开发更简单。
- UI设计中的参照框架 : 学习封装局部上下文如何提升渲染决策。
- Frost, B. (2016). Atomic Design. atomicdesign.bradfrost.com
- 爱因斯坦, A. (1905). 关于运动物体的电动力学. Annalen der Physik.
- Black, A.P., 等. (2007). 行为的可组合单元. 在 Software–Practice & Experience, 39(1),19–39.
- Wuyts, R., 等. (2015). 面向对象系统的可塑性工具. 在 Journal of Object Technology, 14(2),1–35.
- W3C. (2018). Web 内容无障碍访问性指南 (WCAG) 2.1. w3.org
- Nuxt Gravity Documentation (即将发布)
- Marcotte, E. (2010). 响应式设计. alistapart.com
在整个文章中,我们有意区分了Mouldable UI这一通用概念与我们使用Nuxt Gravity进行的具体实现和解读。通过强调原则这一概念,我们展示了如何通过约束将相关的一组令牌打包成一个整体,从而将高层次的概念封装成可重用的包体。这种方法通过消除复杂的非行为逻辑,使组件代码更加简洁,更易于维护。
在 MouldableGravity 示例中,我们假设重力的计算由工具组件内部负责,不需要开发人员传递任何属性。这简化了组件的使用,并专注于渲染逻辑的实现,让开发人员可以放心,组件会根据上下文显示合适的内容。
原则使我们能够以模块化和可重用的方式表示复杂的设计方面,如排版、可访问性、本地化、布局,甚至整个 CSS 框架。通过将原则与参考框架和相对论视角相结合,我们可以创建不仅更具适应性、更情境感知,而且更易于开发和维护的用户界面。
就像爱因斯坦扩展了伽利略的相对论来适应新的时空理解一样,我们可以通过采用这些创新概念来扩展我们对UI设计的理解。这将开启更具有响应性、情境感知性和以用户为中心界面的可能性,这些界面能更好地适应用户需求和技术进步不断变化的趋势。
感谢您探索这些想法,并思考它们可能如何影响未来界面设计的发展。
注意:虽然我们通过我们提出的框架讨论了可塑性用户界面和相对设计等概念的具体实现和解释,这些概念有着丰富的历史和多种实现方式。所提供的示例展示了如何将这些概念应用到现代用户界面开发中。
共同学习,写下你的评论
评论加载中...
作者其他优质文章