在当今的软件工程中,没有比Web开发更艰巨的任务了。
Web应用程序的典型规范可能是这样的:应用程序必须在各种各样的浏览器上工作。它必须以60fps的速度运行动画。它必须对触摸有立即反应。它必须符合一组特定的设计原则和规范。它必须适用于几乎所有可以想象到的屏幕尺寸,从电视、30英寸显示器到手机和表盘。它必须经过良好的设计和长期的可维护。
随着最新的Web技术的出现,这个列表越来越长:Web应用程序必须离线工作。它必须能够发送推送通知。它必须在后台同步。
当然,并不是所有的新Web项目都必须满足这一套完整的要求——有些可能是更成熟的单页应用程序,有些则更专注于发布或电子商务,但应用程序的多样性使Web开发人员的工作更加困难。
当Web应用程序的期望满足Web平台的实际情况时,真正的挑战就出现了。可用来构建Web应用程序的原材料远远没有跟上。html的构建模块,如“
”,“
因此,Web开发社区已经发展出了大量的框架来解决从平台提供的基本元素构建合理接口的问题。可用的Web框架的范围和多样性是一个巨大的繁荣的生态系统,只有像Web这样强大和灵活的平台才能支持。在撰写本文时,TodoMVC (图1),10框架使用的展示。这个欣欣向荣的框架生态系统真是令人惊叹。
或者是吗?
尽管许多Web框架都是令人难以置信的工程成就,非常受欢迎,并且拥有自己的大型生态系统,但多框架模型仍然存在一些限制Web开发人员生产力的关键问题。
框架是影响广泛的硬依赖.HTML、CSS和JavaScript固有的全局特性是推动框架成为无所不包的工厂而不是即用即付工具包的众多因素之一。选择Web框架通常是新Web项目中的第一个主要技术决策。因为框架往往是全面的,几乎每一行代码或标记项都必须在编写时考虑到框架。例如,Angular提供了复杂的视图管理和路由、依赖注入、国际化和可访问性特性、低级动画支持等等。Meteor提供了整个前端和后端堆栈,从UI库到数据库驱动程序。这些平台本身都是功能非常齐全的应用程序平台,但从第一天起就会导致锁定,并且很难进行迁移。如果您选择切换框架,那么您可能要从头开始。
Fashionability.Web框架就像季节一样来来去去。图2显示了五个JavaScript库的流行程度的上升和下降,根据谷歌趋势。Web开发社区一直在渴求下一个新事物,因此Web应用程序需求、设备和浏览器功能的发展如此之快,工具也必须迅速发展以跟上。不幸的是,这意味着昨天的热门新框架可能成为今天的旧新闻,公司在一项技术上的大量投资可能很快就会过时。为了在就业市场上保持竞争力,Web开发人员必须跟上最新的技术,在不断加速的Hacker News框架公告、教程和入门套件的跑步机上奔跑。
缺乏互操作性.健全的组件模型对于可伸缩的接口开发至关重要。框架通常为组织和呈现接口定义自己的组件模型。Angular有指令,React和Ember都有自己的“组件”概念。然而,在一个框架模型中构建的组件在该框架之外没有任何意义——你不能在Ember应用中使用Angular组件,除非包含多个重叠和冗余的依赖项。再加上框架经常需要的锁定,缺乏互操作性使得在Web上编写普遍可重用的封装组件几乎不可能。
圣杯,“金发姑娘”解决方案,将是Web开发人员能够选择最适合他们试图解决的问题的应用程序体系结构,并且能够跨项目重用接口组件。Web开发社区可以为每个框架和组织理念拥有繁荣的生态系统,以及一个共享的、通用的组件生态系统,可以在任何Web应用程序中使用,而不考虑框架。大型组织可以共享符合一致风格的全球维护组件集,但所有团队都可以使用它们,而不管它们的栈是什么。
这个Web开发乌托邦似乎是不可能实现的,或者至少在技术上是不可行的,因为它需要不同框架之间就组件的一致处理达成广泛的协议。然而,Web已经有了这些通用组件——tml元素本身的先例。
此外,
它是可组合的(图3A).
这是完全声明(3 b)。可以使用标记中的属性应用各种不同的特性。
它是灵活的(3 c)。根据其子和属性的不同,它可以提供不同的接口和功能。
它是宽容(3 d)。错误的子程序不会使应用程序崩溃,而只是被忽略。
这是内部可访问的(3 e)。一旦集中,它就会提供所有必要的句柄以便访问。
除了它以声明方式提供的功能外,
最后,
"
有了可扩展网络宣言,14浏览器供应商果断地选择了后一种方法,倾向于提供扩展Web平台特性所需的原语,而不是直接在平台中提供更高级别的抽象。
构建这样一个元素需要什么?为了构建像
因此,要创建一个类似的自定义元素,开发人员需要:
定义它的API:为元素命名,并为其提供命令式方法和可用于影响其行为的声明性属性。
定义它的模板:如果元素需要任何本地UI,则为它提供一些基本的可视化布局。
从文档封装它元素的内部内容应该对文档不可见。也就是说,向文档中添加元素不应产生意想不到的副作用。
定义其组合模型:指定元素可以接受什么类型的子元素以及它如何管理它的子元素。
管理其依赖关系:一个自定义元素应该能够在它的本地UI中使用其他元素,因此应该能够指定和加载它所依赖的任何元素的定义。
当然,您可以在框架级别构建这样的封装和模板特性,许多框架都是这样做的。但是要实现组件广泛互操作的梦想,需要在平台级别提供这些特性,以便使用它们构建的组件可以重用,就像
Web Components是一些新的W3C规范的总称,这些规范为开发人员提供了构建这种可互操作的平台级特性所需的基本要素。组成Web组件的各个规范几乎直接映射到创建真正可互操作元素所需的特定功能。
定义它的API:自定义元素规范2描述如何为元素命名、定义API表面积以及如何响应其生命周期中的不同事件。自定义元素的注册归结为一个简单的调用,如中所示图4.
这允许开发人员为元素指定一个标记,并传入元素的所有实例的原型。此时,文档中“
自定义元素规范中定义的生命周期回调让元素作者在其生命周期的特定阶段对元素进行更细粒度的控制。这些回调包括"createdCallback ",当元素被创建并注册时调用;"attachedCallback ",当元素被插入到文档中时调用;"detachedCallback ",当元素从文档中删除时调用;以及“attributeChangedCallback”,当元素的属性被设置、更改或删除时调用。
在第二个文档之间。通过registerElement参数和attributeChangedCallback,元素作者可以指定元素的命令式和声明式api。
定义它的模板:许多元素都有一些包含的UI,如按钮、输入、选择、标题和列表。要构建真正的平台级元素,元素作者应该能够为自己的元素指定UI。而不是定义一个新的DSL或公开c++钩子,Web开发人员应该能够使用Web本身的语言html和csss来定义元素的模板。
真正的模板有几个关键属性。模板的存在不应该对文档产生副作用,应该显式地选择模板以便使用,因此应该封装在远离主文档的地方,在实际克隆和使用之前它应该是惰性的。
Web上的模板问题是所有UI框架都面临的问题。为了提供这种行为,已经发展了许多变通方法,但没有一个满足真正模板的所有标准。有些模板尝试在主文档中使用带有“display: none;”的标记块来隐藏它,直到克隆并使用它,但这可能会对布局和性能产生副作用。在