【问题标题】:AngularJS 1.5 - Iterate and set child components' propertyAngularJS 1.5 - 迭代和设置子组件的属性
【发布时间】:2017-04-14 20:12:41
【问题描述】:

我有一个父组件,它在 ng-repeat 中创建“n”个子组件。每个子组件在其模板中都有一个手风琴元素(来自 ui-bootstrap 指令)。
从父组件我想使用父组件级别中的链接折叠或展开所有手风琴。每个子手风琴都可以单独展开/折叠,设置本地 vm.isAccordionExpanded 变量。

我打算用$scope.$broadcast()从父母那里通知孩子,他们每个人都会用$scope.$on()拦截事件并设置一个本地布尔变量vm.isAccordionExpanded来分别打开/关闭手风琴。

父组件模板:

<span id="accordionListCommands" ng-if="vm.pastVisits.totalResults > 0">
    <span  id="collapseAllAccordion">
        <a ng-click="vm.collapseAll()" href="">
          <i class="fa fa-minus-square" aria-hidden="true"></i></a>
    </span>
    <span  id="expandAllAccordion">
        <a ng-click="vm.expandAll()" href=""> 
          <i class="fa fa-plus-square" aria-hidden="true"></i></a>
    </span>
</span>

<div ng-repeat="visitItem in vm.pastVisits.data">
    <visits-list-component visit="visitItem"></visits-list-component>
</div>

父组件js文件:

$scope.$on('collapse-all-accordion', function () {
    vm.isAccordionExpanded = false;
});

$scope.$on('expand-all-accordion', function () {
    vm.isAccordionExpanded = true;
});

子模板:

<uib-accordion close-others="false">
    <div uib-accordion-group is-open="vm.isAccordionExpanded">

//Rest of the template


有没有更好或更高效的方法来实现这一目标?

【问题讨论】:

  • 看起来不错。始终在 ng-repeat 中使用 track by 以提高性能。此外,您可以使用is-open="vm.isAccordionExpanded || allExpanded",并将后一个变量设置为 true 以展开全部。
  • 感谢您提醒我有关 track bz Index 的信息,我编辑了答案以显示在触发事件时如何设置 vm.isAccordionExpanded 变量。我认为没有添加 allExpanded 变量的逻辑就足够了,还是我遗漏了什么?
  • 是的,您的逻辑运行良好,只是它不会设置多个事件侦听器,而是只会在摘要周期内执行此操作。不确定您将获得多少性能。无论如何,您的代码对我来说看起来不错。

标签: javascript angularjs angular-ui-bootstrap


【解决方案1】:

您这样做的方式不正确,也不是编写它的角度方式。 而是使用一种方式的数据绑定或两种方式的数据绑定:

bindings: {
  visit: '<' // or ('=') respectivly
}

然后像下面这样实现你的collapseAll函数:

angular.forEach( vm.pastVisits.data,function(visitItem) { 
  visitItem.isAccordionExpanded = false;
});

那么在访问组件中可以写:

vm.$onChanges = function() {
 if(changes.visit) {
   vm.isAccordionExpanded = changes.visit.currentValue.isAccordionExpanded;
 }

}

甚至更好,而不必放置 $onChanges 监听器:

<uib-accordion close-others="false">
<div uib-accordion-group is-open="vm.visit.isAccordionExpanded">

【讨论】:

  • 您的方法的好处是不使用事件,但我个人不喜欢它(不是说这是不对的),因为您正在添加一个与访问模型完全无关的属性(isAccordionExpanded)。我打算让子组件使用“require”从父组件获取 isAccordionExpanded 标志。 Todd Motto 有一篇关于这种方法的博客文章,这似乎是“角度方式”
  • 好的,关于“要求”,耦合组件是一种不好的做法。如果您的组件尽可能地解耦,那总是最好的。如果组件在没有父上下文的情况下无法存在,您应该只使用“require”。在这种情况下,您的子组件是一个简单的手风琴,可以单独存在并且与其他组件没有任何交互,因此您不应该使用 require。至于 Todd 的座右铭,你可以阅读他的风格指南toddmotto.com/rewriting-angular-styleguide-angular-2,你会看到不推荐使用事件系统。
  • 至于事件系统,它从来没有被用来以这种方式更新数据。为此,您有数据绑定,并且从 Angular 2 开始,使用“on-update”绑定方法的单向数据绑定正在替换 2-way 数据绑定。但是,在您的情况下,您不需要更新绑定功能或 2 路数据绑定,因为您的子组件没有更新父组件。最后,关于 isAccordionExpanded,它应该首先存在。因此,最干净的方式和最少的代码只是创建一种方式数据出价并使用 $ctrl.visit.isAccordionExpanded
  • 感谢新样式指南的链接,我错过了那篇文章。最后我重构了我的代码,现在通过使用建议的额外变量更容易了。
  • 是的,我会更新我的答案,额外的绑定变量是最好的
猜你喜欢
  • 2017-08-12
  • 2018-02-02
  • 2017-06-01
  • 2016-11-19
  • 1970-01-01
  • 2017-03-17
  • 1970-01-01
  • 2017-09-08
  • 2010-10-28
相关资源
最近更新 更多