AngularJS 指令 - 设置多个指令元素的顺序(不是指令的优先级,而是元素的优先级)
Posted
技术标签:
【中文标题】AngularJS 指令 - 设置多个指令元素的顺序(不是指令的优先级,而是元素的优先级)【英文标题】:AngularJS directive - setting order for multiple directive elements (not priority for directives, but priority for the elements) 【发布时间】:2013-08-05 16:07:47 【问题描述】:考虑这个带有指令“foo”的标记:
<div foo run="3"></div>
<div foo run="1"></div>
<div foo run="2"></div>
使“foo”按指定顺序而不是从上到下 (3,1,2) 运行的好方法是什么? 我唯一能想到的就是跟踪已经运行的内容并在不正常的项目上返回 false,然后让 angular 尝试再次运行它们并重复直到它们全部完成。但这对我来说听起来很糟糕,因为它必须重复很多次...... Angular 有内置的东西可以使用吗?有没有理想的方法来处理这个问题?
【问题讨论】:
我认为了解更多关于您在 foo 指令中所做的事情以及顺序的重要性的信息会很有帮助。使用父指令,您可以捕获子指令,然后在单独的步骤中处理它们。 嗯。这是一个有趣的想法。我会咬紧它一会儿。我的实际指令正在做的是加载各种内容,其中一些内容比其他内容重要得多。它实际上是一个插件加载器,处理控制器/模板的延迟加载。到目前为止,它的加载速度非常快,但我也想尝试使用一个良好的优先级系统。目前,内容只是从上到下加载。如果左侧边栏优先于主要内容主体,这可能是一个问题。 我明白了,您的意思是远程请求的内容,并且您想管理加载顺序? 【参考方案1】:好的,这是我的解决方案,虽然它更像是一个模板。
Fiddle (check the console log to see the result)
我已将 foo
指令包装在 fooParent
指令中,如下所示:
<div foo-parent>
<div foo run="3"></div>
<div foo run="1"></div>
<div foo run="2"></div>
</div>
fooParent
指令的存在几乎可以做三件事:
-
向
foo
项目公开函数,以便将它们添加到常规列表中
维护foos
的列表,将在链接后排序
按指定的运行顺序处理每个foo
。
看起来像这样:
app.directive('fooParent', function()
var foos = [];
return
restrict: 'A',
controller: ['$scope', '$element', '$attrs', '$transclude', function($scope, $element, $attrs, $transclude)
this.addFoo = function(runOrder, element)
foos.push(
run: 1*runOrder, // make sure run is an integer
element: element
);
;
],
link: function(scope, element, attrs)
foos.sort(function(a, b)
return a.run - b.run;
);
// process all children here
angular.forEach(foos, function(foo)
console.log(foo);
);
;
);
而foo
看起来就像:
app.directive('foo', function()
return
restrict: 'A',
require: '^fooParent',
link: function(scope, element, attrs, fooParent)
fooParent.addFoo(attrs.run, element);
;
);
显然,您必须找出处理远程加载内容的最佳方式,尤其是在您希望连续加载内容的情况下。您的foo
指令将变得更加简化,因为加载和处理必须在fooParent
中进行。
【讨论】:
看起来不错。我要在早上潜入,看看我在哪里:) 只是提醒一下,元素相互嵌套,这是不可取的。我也得到 2,1,3 而不是 3,1,2。 哦,当然。我们省略了 。哈哈,疲劳对大脑有奇效:) 我更正了嵌套问题(是的,写得太晚了),我还更正了 run 到整数的转换,这将有助于排序。最后,如果要先运行最高的运行号,请将排序功能更改为b.run - a.run
(交换a
和b
)。
我只是做了同样的事情 :) 它看起来确实很好用!我有一个想法,我也想尝试,只是为了它。一会儿我会发帖。【参考方案2】:
感谢 OverZealous 启发了我的回答。在这里测试一下。 http://jsbin.com/apumaj/21/edit
html(指令输出当然会按这个顺序显示)
<div foo run="7"></div>
<div foo run="3"></div>
<div foo run="1"></div>
<div foo run="2"></div>
并且指令(使指令输出以“运行”顺序加载)应该是不言自明的
app.directive('foo', function()
var foos = [];
var foosLength = document.querySelectorAll('[foo]').length;
return
restrict: 'A',
link: function(scope, element, attrs)
foos.push(element:element, run:attrs.run);
if (foos.length === foosLength)
foos.sort(function(a, b)
return a.run - b.run;
);
console.log('ran in this order:');
for (var i=0; i<foosLength; ++i)
//process foos!
var foo = foos[i];
console.log(foo.run);
foo.element.text(foo.run);
;
);
【讨论】:
我选择了这种方法而不是 OverZealous 提出的解决方案,因为它不需要非语义和其他不必要的 dom 元素和额外的指令。它更易于理解/可读,性能应该稍微好一些。 从那以后我改变了主意,开始喜欢 OverZealous 的回答 :) 选择没有父元素会强制您使用 DOM 方法 (querySelector)。旁注是当您嵌套<foo>
s 时,这两种解决方案都不起作用,除非您想选择它们而不考虑嵌套深度。 Angular 的哲学是结合使用子/父指令和require
来定义 DOM 元素之间的依赖关系。因此我认为@OverZealous 的解决方案更优雅。
@frankvanwijk 绝对。这就是为什么我将其标记为接受。 :) 我的回答确实更巧妙地解决了我的实际问题,因为我需要它是全局的,但使用父元素使其全局化肯定更好,而不是强制它。那时我没有意识到这一点。以上是关于AngularJS 指令 - 设置多个指令元素的顺序(不是指令的优先级,而是元素的优先级)的主要内容,如果未能解决你的问题,请参考以下文章