【发布时间】:2016-12-06 15:55:37
【问题描述】:
我有一个下拉 element 指令,实质上是一个带有附加功能的样式化下拉列表。
我的下拉控制器有一个名为 openDropdownItems 的函数,它会在应该显示列表时执行。
然后我还有另一个名为 setInViewWhen 的 attribute 指令,它提供了一个表达式,当条件为真时元素应滚动到视图中。
<x set-in-view-when="something.item === selectedItem">
这只是应用了我的属性指令的一些 X 元素的示例。
问题是我希望我的下拉列表项(即 LI)在它们上具有此指令,因此当用户使用键盘在它们上导航时,当它们通过可见视口时它会自动在视图中滚动它们。这些项目是显示在可滚动容器中还是作为一个整体显示在比浏览器视口更长的列表中并不真正相关。
主要思想是滚动以跟随下拉列表选择。是否应该滚动主窗口。
问题
我可以使我的setInViewWhen 指令完全独立,但这意味着只要项目的条件发生变化,我就必须搜索最近的可滚动容器。这似乎是我想避免重复的相当多的处理(我需要向上遍历 DOM,检查每个节点的计算样式表属性 OverflowY + 一些额外的检查。
这基本上看起来是多余的,因为每当我获得最接近的滚动祖先时,所有具有相同指令的兄弟元素都可以重用计算结果。
问题 1
如何在同级指令之间共享这些知识?如果我要触发一个事件,如果没有任何额外的处理,我将无法知道接收者是否是兄弟姐妹。
问题 2
而不是每次当我的指令条件变为真时检查可滚动容器,理论上我可以更改下拉父级的openDropdownItems 以首先完成它的原始执行,然后还执行可滚动性检查并将其结果与我的指令条件一起使用.
我可以通过指令requires 属性在我的指令中访问下拉菜单的控制器,并在链接后阶段对其进行调整。
但这也意味着我不能在我想要的下拉列表之外使用我的指令,因为它是一个普遍可用的指令,我可以附加在我的应用程序中的几个元素上,以便在某些条件下将元素滚动到视图中。
你会建议如何做到这一点?
【问题讨论】:
-
一些想法/观察: (1) 对于 Q1,兄弟指令之间没有直接的通信方式。我通常创建一个包装父指令来中继消息。 (2)我猜条件
something.item === selectedItem介绍手表;对于选择项目的列表,这可能是很多手表并且不利于性能。我宁愿在 LI 的父级中有一个手表,并在那里添加“滚动到视图”逻辑。 -
(3) 考虑到第 2 点,您仍然可以拥有一个独立的
setInViewWhen指令(似乎很有用)并且拥有您的X-select 替换控制器指令与它共享代码。例如。创建一个具有通用功能的服务,创建一个包含 JS“类”的角度值,并让setInViewWhen和X指令的控制器从它扩展(或其他解决方案)。 -
(4) 相对于 Q2:虽然孩子可以要求他们的父母并更改其中的方法(这种技术甚至得到 Angular 的认可,请参阅 ng-model 和自定义控件),但会有很多孩子们改变它,这可能会导致一团糟......
-
当然。每个指令都有自己的手表,可以按照
$scope.$watch($parse($attrs.setInViewWhen)($scope),...)`的方式执行某些操作,您对 (4) 非常正确,该函数本身会被包装很多次。馊主意。可能是(3)是实际创建两个指令的方法:一个与下拉菜单相关,另一个与独立指令相关。但是我可以轻松地创建两者的基本控制器,而不是创建服务,因为我正在使用 TypeScript,然后扩展子类。 -
是的,基本控制器很棒。
标签: angularjs angularjs-directive