AngularJS的ng-include作用域

AngularJS ng-include scope

本文关键字:作用域 ng-include AngularJS      更新时间:2023-09-26

我是一名经验丰富的开发人员,但我是angularjs的初学者,我有一段时间没有使用javascript了。

我的网站被分成几个angularjs应用程序。但是两个应用程序可能必须显示相同的"实体"类型。

例如,我的第一个应用程序是专门用于书籍,并将从api(例如:http://example.com/Books)接收以下json数据:

[
    { "id":"1", "title":"...", "publisher":"..." },
    { "id":"2", "title":"...", "publisher":"..." },
]

第二个应用程序更通用,将从api(例如:http://example.com/Things)接收以下json数据:

{
    "count":"3",
    "items":
        // my two books
        { "type":"book", "data":{ "id":"1", "title":"...", "publisher":"..." } },
        { "type":"book", "data":{ "id":"2", "title":"...", "publisher":"..." } },
        // and other things
        { "type":"movie", "data":{ "id":"45", "title":"...", "producer":"..." } },
    ]
}
我创建了一个模板"book.html":
<div>{{book.title}} ({{book.publisher}})</div>

我在我的视图中使用:

<ul><li ng-repeat="book in books" ng-include="'book.html'"/></ul>

到目前为止一切顺利…

我现在想使用相同的模板——不复制它——在第一种情况下显示图书,在第二种情况下显示图书,如:

<ul><li ng-repeat="item in items" ng-include="item.type+'.html'"/></ul>

我的问题不是动态模板。我的问题是:在我的book.html模板中,我使用"book.html"。,但对于我的第二个应用程序,我需要使用"item.data.title"。

在我看来,理想的情况应该是这样的:

<ul><li ng-repeat="item in items" ng-include="item.type+'.html'" ng-something="book=item.data"/></ul>

我可以通过将图书数组"转换"为第二种格式来解决这个问题。但我想我误解了一些东西,也许我以错误的方式使用了angularjs。

你能给我一些提示吗?

谢谢

使用指令。它们一开始看起来很吓人,但是对于这样的用例来说它们非常简单:

app.directive("book", function() {
    return {
        restrict: "A",
        templateUrl: "book.html",
        scope: {
            book: "="
        }
}); // isnt' it simple?

第一个例子:

<ul>
    <li ng-repeat="book in books">
        <span book="book"></span>
    </li>
</ul>

第二个案例:

<ul>
    <li ng-repeat="item in items" ng-switch="item.type">
        <span ng-switch-when="book" book="item.data"></span>
        <span ng-switch-when="movie" movie="item.data"></span>
        ...
    </li>
</ul>

Angular有一个名为ng-init的内置指令,可以用来计算作用域上的表达式,这意味着它可以用来设置作用域变量,而无需创建控制器或自定义指令。

在本例中

    <li ng-repeat="item in items" 
        ng-include="item.type+'.html'" 
        ng-init="book=item.data"/>

应该可以达到这个目的,尽管文档指定它不适合这个用例:

ngInit的唯一合适用法是for混叠ngRepeat [$index, $even等]的特殊属性,如下面的演示所示。除了这种情况,应该使用控制器,而不是ngInit初始化作用域的值。

https://docs.angularjs.org/api/ng/directive/ngInit

如果您不想更改模板的结构,则需要更改数据的结构。创建控制器:

app.controller('BookOrMovieController', function($scope) {
    if ($scope.item.type == 'Book') {
        $scope.book = $scope.item.data;
    }
    if ($scope.item.type == 'Movie') {
        $scope.movie = $scope.item.data;
    }
});

然后在包含的模板元素上实例化控制器:

<ul><li ng-repeat="item in items" ng-include="item.type+'.html'" ng-controller="BookOrMovieController"/></ul>