操纵几个元素的Angular JS指令

Angular JS directive manipulating several elements

本文关键字:Angular JS 指令 元素 几个 操纵      更新时间:2023-09-26

据我所知,无论出于何种原因(显示数据、控制布局行为等),每当我们想在Angular JS中进行DOM操作时,我们都应该使用指令。现在,有时对一个元素的一些DOM操作需要其他DOM元素的信息来操作。

一个真实的例子:假设我们想要调整一个div的大小以适应整个屏幕。div有一个定义的高度我们想要根据内容改变这个高度等等来让div填充屏幕。通常,在进行此类操作时,我们需要考虑其他DOM元素,如header等。

另一个例子如下:假设我们有一个登录表单,在表单的底部我们想要一个链接,允许用户在没有帐户的情况下注册。当用户单击该按钮时,它应该将表单从登录切换到注册(通常另一个表单是编码和隐藏的)。这很好,如果我们在链接上添加一个指令来做这件事,它需要操作表单div,如果我们在表单中添加div,它需要与链接通信。

在这些情况下(我真的很一般,这只是两种可能的情况),是否有一个关于我们应该如何行动的一般指导方针?

我的意思是,我们有一些DOM元素<A>,我们想以某种方式操作它,但要做到这一点,我们需要关于另一组DOM元素<A1>的信息,…<An>,那么我们如何用一致性来处理这个呢?

我想使用require和共享指令控制器。但是这很奇怪,再次采取调整大小的例子,我们将<div maintain-height>作为maintain-height的指令与逻辑来调整这个div的大小。然后与它通信,我们需要在触发调整大小的指令需要这个的每一个其他地方。这似乎不自然,但在其他情况下,我认为感觉是一样的。

那么,当我们遇到这种情况时,我们如何处理它来维护所有的东西都写得很好,可维护的,可测试的,等等?

这样做的需求可能表示一个非角架构。您需要的任何信息都应该在视图模型中,或者在当前范围中,或者在您可以轻松访问的另一个范围中。您可以通过广播(或发出)消息在作用域之间进行通信。你也可以把你需要的数据放在一个服务中,然后把它注入到你需要的控制器中。

如果出于某种原因你必须访问其他元素并直接从它们读取数据,你可以在指令中使用普通的jQuery/jQLite方式。还有$document服务

您描述的特定用例看起来很奇怪。为什么不直接使用CSS来处理DOM元素的大小调整?

您的其他用例(更改表单)将由作用域变量(如showLogin)处理。根据该变量的值隐藏或显示两种不同的形式。还是我遗漏了你的要求?

所有的DOM操作应该总是总是在AngularJS的指令中完成。要在指令之间共享非dom数据,可以使用控制器和/或服务。

在你的第一个用例中,我会使用像Twitter-Bootstrap这样的东西来做响应的东西。Bootstrap是一个CSS框架,虽然它有JavaScript组件。其中一个CSS组件是调整元素的大小,使它们在特定的屏幕尺寸上看起来更好。我所见过的大多数涉及屏幕尺寸的课程都有4种尺寸:小屏幕,如智能手机屏幕,平板电脑大小的屏幕,中小型电脑和大型电脑。这些大小似乎可以工作,除了直接在两者之间的大小,我认为没有广泛实现。这些类通常放在容器元素上,比如<div> s,尽管也有一些类是附加在头文件上的,等等。

对于第二个用例,登录总是一个挑战。我不确定如何解决您的具体情况,因为我不需要使网站非常安全,但我将首先定义一个变量在控制器中登录,并使用它来决定什么登录状态放置页面。该变量将使与此登录状态对应的指令可见,而其他指令不可见。当用户按下链接时,它会改变这个变量,从而改变可见指令。我知道我说过总是在指令中做DOM的东西,但这是一个边缘情况,并处理范围,这是一个控制器的权限。

指令中DOM依赖关系的问题在于,随着指令的编译和链接,DOM会发生变化。

然而,只要指令遵守规则,你就可以依赖一些东西:

  1. 在编译阶段,元素是通过从最外层元素到最内层元素从父元素到子元素遍历DOM树并按优先级顺序(从高到低)调用它们的'compile'函数来编译的。
  2. 指令的编译函数应该只修改它的子指令(而不是它的父指令或祖父母指令)。原因是子元素还没有被编译,所以修改它们是安全的,angular编译器最终会遍历DOM树并编译修改后的DOM。父元素已经被"遍历"过了,编译父元素的机会来了又去了。如果一个指令改变了它的父指令,它需要重新编译,这通常不是一个好主意(无限递归)。
  3. 在(后)链接阶段,元素的链接顺序与编译顺序相反。这意味着当一个指令被链接时,它的内容(或子指令)已经被链接了,你可以依赖于子指令的DOM树。但是父元素还没有被链接。

知道了这些,你怎么能设计一个有外部DOM依赖的指令呢?那么,您需要知道编译和链接完成后DOM的最终状态。为此,我建议至少使用两个指令:

  1. 一个位于最高层的主指令,在那里你可以公开控制器函数,这些函数可以被调用来获取外部DOM数据(基于DOM树的当前编译和链接状态)。
  2. 一个嵌套在主指令中的子指令,可以在主指令完成最后的链接阶段时得到通知。

不幸的是,这并不能保证$watch处理程序(甚至是父链接函数)会以意想不到的方式修改DOM。如果您知道哪些指令在起作用,您应该能够使其可靠地工作。