Javascript,HTML和CSS之间的紧密耦合:更现代的方法?


29

看到Java绑定到某些选择器以查找元素,存储数据和侦听事件是很常见的。看到这些用于样式的选择器也是很常见的。

jQuery(及其选择器引擎Sizzle)通过使用CSS类型的语法引用元素来支持和促进这一点。因此,在构建项目时,这种技术特别难以“取消学习”(或重构)。

我已经了解到,这是HTML和Javascript开发历史的结果,并且已经建立了浏览器来有效使用/解析/呈现这种耦合。但是随着网站变得越来越复杂,这种现实会给组织和维护这些单独的层带来困难。

我的问题是:现代网站是否可以避免这种情况?

如果我是前端开发的新手,并且希望以“正确的方式”学习事物,那么值得一开始学习去耦和避免这种依赖吗?这是否意味着避免使用jQuery,而推荐使用可促进更解耦结构的库?


1
这样的事情如何运作?例如,您如何禁用页面上的控件而不实际以某种方式触摸该控件或不知道该控件?(这是我的一点说法,即您需要更具体地了解去耦的含义,最好是包含一些示例,即使它们是人为设计的)。
罗伯特·哈维

2
当谈论脱钩html,css和js时,最重要的是使用类选择器,而不是其他选择器,这是oocss和BEM之类方法论的核心概念。
天使

学习React或Web组件,您将不再需要为JS中的选择器而烦恼。
安迪

Answers:


35

没有办法避免这种情况。它们之所以耦合是因为它们彼此交互。如果您的JavaScript打算进行任何类型的DOM操作,则需要一种引用DOM的方法。

有很多约定。

级别2 DOM API提供了getElementById,getElementByTagName和getElementsByName方法。时至今日,这些都是任何类型的DOM遍历的主力军。所有其他更高级的jQuery选择器最终都会解析为这些组合,并且/或者直接遍历每个DOM节点(这是执行getByClassName的方法)。

没有其他快捷方式。Javascript需要知道做什么和在哪里。通常,如果元素具有仅与脚本编写相关的ID或类,那么很多人会在其前缀上加上js-其他明显的标志。

另一个较新的约定是数据属性选择。

<ul data-myapp-sortable="true">

jQuery('[data-myapp-sortable]').makeSortable();

数据属性通常用于脚本编写目的,使用它进行选择很有意义。缺点是,这比使用getElementById()慢。

另一种方法是angularJS使用的方法,该方法创建一个视图模型。在此约定中,任何一种脚本功能均由诸如ng-disabled ng-href等等的特殊指定属性指定。您无需在JavaScript中添加选择器。HTML文档成为脚本内容和脚本编写方式的主要授权,而javascript则可以对其进行抽象处理。这是一个很好的方法,但是显然比以前的方法具有更高的学习曲线。同样,必须考虑性能。

但是,永远不要以为您可以编写交互式HTML和javascript,并且以某种方式使这两个部分彼此都不了解。更多关于如何将引用限制为依赖项。


2
出色的答案,+ 1。如果仅提及数据属性作为避免紧密耦合的机制
弗格斯在伦敦,2014年

3
数据属性不是万能药。这些天它们非常受欢迎,人们除了厨房水槽外,都把它们放在里面。许多框架(例如jQuery UI)广泛使用它们。您必须严格遵守命名空间和其他约定,以避免出现问题。它们有助于将HTML与JS分离,但是并不一定会使调试变得更容易。
mastaBlasta 2014年

我从未理解过为什么需要重新构造使用类,ID和数据属性作为钩子和状态标志的原因。在这方面,Angular所做的全部工作就是降低性能,并用一种​​新的约定代替了众所周知/已被理解的约定,该约定要求一个人了解如何以“ Angular的方式”做到这一点,并发明自己的属性和标签。那里没有巨大的学习曲线。它只是速度较慢,与完全合理和众所周知的惯例以及完全不必要的IMO相背离。
埃里克·雷彭

9

如果您愿意放弃所获得的交互性,则可以完全避免使用Javascript。诸如ASP.NET MVC之类的框架非常擅长提供仅包含HTML,CSS和SUBMIT按钮的页面。

好。也许这有点极端。

Web应用程序中的解耦已经发生在许多级别。REST应用程序允许您根据与URL关联的“网络资源”来定义应用程序。视图模型允许您向与域模型分离的UI呈现数据,但是具有正确显示它所需的形状。服务层允许将一个UI交换为另一个UI,依此类推。

从历史上看,始终在交互性和耦合之间进行权衡。网页的交互性越强,与应用程序的联系就越紧密。但是网页中的交互逻辑仅限于网页本身。与服务器的任何耦合都将通过POST或AJAX进行。因此,除了关注数据包在浏览器和服务器之间传递的方式之外,我不确定您是否应该过度关注Javascript级别的耦合。

最“现代”的方法(即本周的风味)可能是SPA应用程序


对我来说听起来并不极端。许多广泛使用JavaScript的站点,甚至没有它们就无法使用,实际上并不需要它。他们的开发人员会有更多线索吗?
Michael Hampton 2014年

5

马丁·福勒(Martin Fowler)将一种方法称为“ 隔离的DOM”,将您的DOM JavaScript与页面逻辑JavaScript分开。

Application Logic <----> DOM Manipulation <----> DOM / HTML

1
+1我完全同意隔离JavaScript <-> DOM逻辑。我真的不喜欢数据属性,因为这些属性与DOM不相关,而与外部工具相关。我觉得更干净的方法是进行某种类型的映射。是的,这可能意味着您有一个文件,其中包含对两个方面的引用(例如JS函数和DOM元素),而不是例如包含JS拾取的一些引用的DOM(可能称为“单方面” ')。但是,如果进行周到的考虑,这将是非常可维护的,可重用的,并且比数据属性可提供更好的关注点分离。
2014年

2

不,不应避免在客户端使用类,元素和ID选择器。 之所以使用该语法,是因为CSS选择器是非常成熟和完善的领域语言,并且具有通用的设计使在程序和设计之间共享页面的通用逻辑模型变得容易得多,这是非常非常好的事情。

尽管可能会滥用此语法并创建一个糟糕且不可维护的应用程序,但无论您使用哪种语言或工具集,这都是可能的。


2
实际上,我建议不要在很多事情上使用类,元素和ID选择器,而应着重使用自定义[data-*]属性选择器,该选择器可以以非常强大的方式使用。
zzzzBov

2
我想到的建议很差,尤其是在编写模块化/可重用的JS时,应该不考虑选择器。对于这些情况,数据属性是一个更好的主意。
Fergus在伦敦,2014年

3
@zzzzBov-我知道这是一个微优化,但是ID和类查找比数据属性查找快得多。但是,是的,我喜欢使用不同的属性集来处理不同问题的想法。
Jimmy Breck-McKye 2014年

0

有人需要为dom的间接访问和缓存层构建jQuery路径管理器接口。

pathMgr.register(name,selector [,isDynamic=false]);
pathMgr.get(name [,refresh]);

然后,

String.prototype.reg([isDynamic=false]);
String.prototype.get(name [,refresh]);

所以,

// at init....
var pathMgr=new PathMgr();
'sidebar-links #sidebar a'.reg();// new registery of selector '#sidebar a' under name 'sidebar-links'
// more, more


// in code
'sidebar-links'.get().css(etc...);
//or
'sidebar-links'.addStyleRule({});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.