【问题标题】:AngularJS component nestingAngularJS 组件嵌套
【发布时间】:2020-08-29 03:38:18
【问题描述】:

我创建了一个组件搜索上下文,效果很好。它是可配置的,它会做它应该做的事情。

<search-context context-name="Groups"
    compare-columns="['displayName']"
    search-manager="$ctrl"
    query-url="/group/search/{{contextId}}"
    icon="fa fa-users"
    on-resolve-item-url="resolveItemUrl(row)"></search-context>

独立运行。

还有各种其他搜索上下文,我想创建一个搜索管理器组件,以便我可以编写如下标记:

<search-manager>
    <search-context context-name="Devices"
                    compare-columns="['displayName']"
                    search-manager="$ctrl"
                    query-url="/device/search/{{contextId}}"
                    icon="fa fa-laptop"></search-context>
    <search-context context-name="Groups"
                    compare-columns="['displayName']"
                    search-manager="$ctrl"
                    query-url="/group/search/{{contextId}}"
                    icon="fa fa-users"
                    on-resolve-item-url="resolveGroupEditUrl(row)"></search-context>
</search-manager>

一般的计划是搜索上下文检查它是否有搜索管理器,如果有,则抑制自己的输入/按钮控件,搜索管理器将提供输入控件并将搜索词提供给搜索上下文。

AngularJS 组件文档中的示例演示了在控件模板中使用 ng-repeat 的 动态 子控件,但不清楚如何设置以处理我建议的显式标记。如果可能的话,我宁愿不需要明确指定 search-manager="$ctrl" 父引用。

如何解决这个问题以及必须研究和理解的支持主题是什么?只是关键概念名称会有很大帮助,但概述和进一步阅读列表会很棒。

我第一次尝试search-manager 的模板看起来像这样

<div>
    <div class="panel-heading">
        <h3 class="panel-title">Search</h3>
        <div class="input-group">
            <input class="form-control" ng-model="$ctrl.term" />
            <span class="input-group-btn" ng-click="$ctrl.search()">
                <button class="btn btn-default">
                    <i class="fa fa-search"></i>
                </button>
            </span>
        </div>
    </div>
    <div class="panel-body">
        <ng-transclude></ng-transclude>
    </div>

</div>

代码如下所示

function SearchManagerController($scope, $element, $attrs, $http) {
    var ctrl = this;
    ctrl.searchContext = [];
    ctrl.registerSearchContext = function (searchContext) {
        ctrl.searchContext.push(searchContext);
    }
    ctrl.search = function () {
        ctrl.searchContext.forEach(function (searchContext) {
            searchContext.search(ctrl.term);
        });
    };
}
angular.module("app").component("searchManager", {
    templateUrl: "/app/components/search-manager.html",
    controller: SearchManagerController,
    transclude: true,
    bindings: {
        term: "@"
    }
});

子组件已被嵌入,但它们需要对 search-manager 组件的引用,而 $ctrl 不在范围内。

我们如何获得对父级的引用?

【问题讨论】:

  • 要考虑的一件事是使用组件回调(即那些 &amp; 绑定)而不是转发上下文。这里的想法是,如果子组件中发生的任何更改绑定到任何公开的回调,父组件都将知道它。您还可以避免将上下文中任何其他不必要的内容泄露给孩子。

标签: angularjs angular-components angularjs-ng-transclude


【解决方案1】:

要获得对父级的引用,您需要做的就是在search-context 声明中的require 父级。双插入符号前缀意味着搜索父母。单个插入符号从当前对象开始,它可以工作但效率稍低。问号的意思是如果找不到就不要吐槽,直接返回 undefined。当组件可能并不总是由搜索管理器作为父级时,这是必要的。

angular.module("app").component("searchContext", {
    templateUrl: "/app/components/search-context.html",
    controller: SearchContextController,
    require: {
        searchManagerCtrl: "?^^searchManager"
    },
    bindings: {
        ...
    }
});

但是如果您需要父级引用子级怎么办?

SearchContextController 中,我们实现了$onInit 生命周期事件处理程序。

    ctrl.$onInit = function () {
        if (ctrl.searchManagerCtrl) {
            ctrl.searchManagerCtrl.registerSearchContext(ctrl);
        }
    };

registerSearchContext 是在父控制器中为此目的定义的方法。该实现本质上是将每个注册的控件推送到我们在其范围内定义的数组属性中,然后父级的方法可以枚举子级。

对于一个指令,这个require 技巧的表达方式略有不同。您必须在指令范围内声明属性 searchManagerCtrl,并直接提供表达式作为 require 的值。

require: "?^^searchManager",

您还必须提供link 函数。 link 函数的参数之一是 controller 并且对 searchManager 的引用将在此参数中传递,此时您可以将其分配给指令范围的属性。 $onInit 生命周期事件仍可用于向搜索管理器注册,但指的是 $scope 而不是 ctrl

【讨论】:

    猜你喜欢
    • 2016-10-09
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 2015-11-14
    相关资源
    最近更新 更多