ChatGPT解决这个技术问题 Extra ChatGPT

部分和模板的复杂嵌套

我的问题涉及如何在 AngularJS 应用程序中处理复杂的模板嵌套(也称为部分)。

描述我的情况的最佳方式是使用我创建的图像:

https://i.stack.imgur.com/V17C3.png

正如您所看到的,这有可能成为一个包含大量嵌套模型的相当复杂的应用程序。

该应用程序是单页的,因此它会加载一个 index.html,该 index.html 在 DOM 中包含一个具有 ng-view 属性的 div 元素。

对于第 1 圈,您会看到有一个主导航,可将适当的模板加载到 ng-view 中。我通过将 $routeParams 传递给主应用程序模块来做到这一点。这是我的应用程序中的示例:

angular.module('myApp', []).
    config(['$routeProvider', function($routeProvider) {
        $routeProvider.                     
            when("/job/:jobId/zones/:zoneId", { controller: JobDetailController, templateUrl: 'assets/job_list_app/templates/zone_edit.html' }).
            when("/job/:jobId/initial_inspection", { controller: JobDetailController, templateUrl: 'assets/job_list_app/templates/initial_inspection.html' }).
            when("/job/:jobId/zones/:zoneId/rooms/:roomId", { controller: JobDetailController, templateUrl: 'assets/job_list_app/templates/room_edit.html' })       

    }]);

在第 2 圈中,加载到 ng-view 中的模板有一个额外的子导航。然后这个子导航需要将模板加载到它下面的区域 - 但由于 ng-view 已经被使用,我不知道如何去做。

我知道我可以在第一个模板中包含其他模板,但是这些模板都会非常复杂。我想将所有模板分开,以使应用程序更容易更新,并且不依赖于必须加载父模板才能访问其子模板。

在圈子 3 中,您可以看到事情变得更加复杂。子导航模板有可能具有第二个子导航,该子导航需要将其自己的模板也加载到第 4 圈中的区域中

如何构建一个 AngularJS 应用程序来处理如此复杂的模板嵌套,同时保持它们彼此分离?

如果您仍在关注此线程,我添加了一个指向新 AngularUI 项目的链接以解决此问题,并添加了由子路由提供支持的第三个演示,而无需对我的回答提供指令。
这个如何? bennadel.com/blog/…
很长一段时间以来我见过的最漂亮的问题:)
同意!喜欢使用模型
在此处的问题中直接添加指向替代方案的链接会很棒。 github.com/angular-ui/ui-router github.com/artch/angular-route-segment github.com/dotJEM/angular-routing

C
Cerbrus

更新:查看 AngularUI 的新项目来解决这个问题

对于小节,它就像利用 ng-include 中的字符串一样简单:

<ul id="subNav">
  <li><a ng-click="subPage='section1/subpage1.htm'">Sub Page 1</a></li>
  <li><a ng-click="subPage='section1/subpage2.htm'">Sub Page 2</a></li>
  <li><a ng-click="subPage='section1/subpage3.htm'">Sub Page 3</a></li>
</ul>
<ng-include src="subPage"></ng-include>

或者,您可以创建一个对象,以防您到处都有指向子页面的链接:

$scope.pages = { page1: 'section1/subpage1.htm', ... };
<ul id="subNav">
  <li><a ng-click="subPage='page1'">Sub Page 1</a></li>
  <li><a ng-click="subPage='page2'">Sub Page 2</a></li>
  <li><a ng-click="subPage='page3'">Sub Page 3</a></li>
</ul>
<ng-include src="pages[subPage]"></ng-include>

或者您甚至可以使用 $routeParams

$routeProvider.when('/home', ...);
$routeProvider.when('/home/:tab', ...);
$scope.params = $routeParams;
<ul id="subNav">
  <li><a href="#/home/tab1">Sub Page 1</a></li>
  <li><a href="#/home/tab2">Sub Page 2</a></li>
  <li><a href="#/home/tab3">Sub Page 3</a></li>
</ul>
<ng-include src=" '/home/' + tab + '.html' "></ng-include>

您还可以在每个部分的最顶层放置一个 ng-controller


我更喜欢你的解决方案。我是 Angular 的新手,从直到今天我对网络的看法来看,这似乎更容易理解。谁知道呢,可能是 blesh 使用了更多的 Angular 框架来做到这一点,但似乎您以更明智的方式用更少的代码行完成了它。谢谢!
@ProLooser 也许您的意思是此链接 github.com/angular-ui/ui-router ...您粘贴的链接已损坏
我遇到与 OP 相同的设计问题。有没有人尝试过 AngularUI 状态机制?我非常不愿意使用另一个 3rd 方库,我宁愿坚持使用 AngularJS 的“做事方式”。但另一方面,路由系统似乎是它的致命弱点......@PhillipKregg,你最终用什么来解决这种情况?
您可以指定 <div ng-include="'/home/' + tab + '.html'" ng-controller="SubCtrl"></div> 以便为子模板使用单独的控制器/范围。或者只需在子模板中的任何位置指定 ngController 指令,以便为每个部分使用不同的控制器。
@DerekAdair 该项目相当稳定(尽管有版本号)并且在一些地方用于生产。它可以防止不必要的控制器重新加载,并且是我建议的解决方案的更好替代方案。
B
Ben Lesh

好吧,因为你目前只能有一个 ngView 指令......我使用嵌套指令控件。这允许您设置模板并在它们之间继承(或隔离)范围。除此之外,我使用 ng-switch 甚至只是 ng-show 来根据来自 $routeParams 的内容来选择要显示的控件。

编辑这是一些示例伪代码,让您了解我在说什么。带有嵌套的子导航。

这是应用程序的主页面

<!-- primary nav -->
<a href="#/page/1">Page 1</a>
<a href="#/page/2">Page 2</a>
<a href="#/page/3">Page 3</a>

<!-- display the view -->
<div ng-view>
</div>

子导航指令

app.directive('mySubNav', function(){
    return {
        restrict: 'E',
        scope: {
           current: '=current'
        },
        templateUrl: 'mySubNav.html',
        controller: function($scope) {
        }
    };
});

子导航模板

<a href="#/page/1/sub/1">Sub Item 1</a>
<a href="#/page/1/sub/2">Sub Item 2</a>
<a href="#/page/1/sub/3">Sub Item 3</a>

主页模板(来自主导航)

<my-sub-nav current="sub"></my-sub-nav>

<ng-switch on="sub">
  <div ng-switch-when="1">
      <my-sub-area1></my-sub-area>
  </div>
  <div ng-switch-when="2">
      <my-sub-area2></my-sub-area>
  </div>
  <div ng-switch-when="3">
      <my-sub-area3></my-sub-area>
  </div>
</ng-switch>

主页面的控制器。 (来自主要导航)

app.controller('page1Ctrl', function($scope, $routeParams) {
     $scope.sub = $routeParams.sub;
});

子区域指令

app.directive('mySubArea1', function(){
    return {
        restrict: 'E',
        templateUrl: 'mySubArea1.html',
        controller: function($scope) {
            //controller for your sub area.
        }
    };
});

我更喜欢 ProLoser 的解决方案,我们在我们的应用程序上做了类似的事情,而且效果很好。 blesh 解决方案的问题是控制器代码进入指令。通常,您在指令中指定的控制器是与 ex: ngModelCtrl 指令密切合作的控制器,它与输入和其他指令密切合作。在您的情况下,将控制器代码放在指令中将是一种代码气味,它实际上是一个独立的控制器。
@blesh,不错!这似乎真的很好解释,但作为一个优秀的 JS 程序员和 AngularJS 的初学者,我不能很好地理解这一点......我和社区真的很喜欢使用这种方法的工作示例的 JSFiddle 链接。仔细研究一下就很容易理解了! :) 谢谢
我认为这个解决方案应该是任何“嵌套视图不起作用”的问题的第一个答案。只是因为它更接近 Angular 意识形态而不是使用 ui-router 等。谢谢。
所以答案是指令?
要突出显示您可以使用的子导航项:coder1.com/articles/angularjs-managing-active-nav-elements 这是一个好方法吗?
a
artch

您也可以出于相同目的签出此库:

http://angular-route-segment.com

看起来和你要的一样,使用起来比ui-router简单多了。从 demo site

JS:

$routeSegmentProvider.

when('/section1',          's1.home').
when('/section1/:id',      's1.itemInfo.overview').
when('/section2',          's2').

segment('s1', {
    templateUrl: 'templates/section1.html',
    controller: MainCtrl}).
within().
    segment('home', {
        templateUrl: 'templates/section1/home.html'}).
    segment('itemInfo', {
        templateUrl: 'templates/section1/item.html',
        controller: Section1ItemCtrl,
        dependencies: ['id']}).
    within().
        segment('overview', {
            templateUrl: 'templates/section1/item/overview.html'}).

顶级 HTML:

<ul>
    <li ng-class="{active: $routeSegment.startsWith('s1')}">
        <a href="/section1">Section 1</a>
    </li>
    <li ng-class="{active: $routeSegment.startsWith('s2')}">
        <a href="/section2">Section 2</a>
    </li>
</ul>
<div id="contents" app-view-segment="0"></div>

嵌套 HTML:

<h4>Section 1</h4>
Section 1 contents.
<div app-view-segment="1"></div>

Artem,你的是我迄今为止找到的最好的解决方案!我喜欢你扩展 angular route 而不是像 angular ui 那样替换它的事实。
D
Dan Ochiana

我也在 Angular 中的嵌套视图中苦苦挣扎。

一旦我掌握了 ui-router,我就知道我永远不会回到角度默认路由功能。

这是一个使用多层视图嵌套的示例应用程序

app.config(function ($stateProvider, $urlRouterProvider,$httpProvider) {
// navigate to view1 view by default
$urlRouterProvider.otherwise("/view1");

$stateProvider
    .state('view1', {
        url: '/view1',
        templateUrl: 'partials/view1.html',
        controller: 'view1.MainController'
    })
    .state('view1.nestedViews', {
        url: '/view1',
        views: {
            'childView1': { templateUrl: 'partials/view1.childView1.html' , controller: 'childView1Ctrl'},
            'childView2': { templateUrl: 'partials/view1.childView2.html', controller: 'childView2Ctrl' },
            'childView3': { templateUrl: 'partials/view1.childView3.html', controller: 'childView3Ctrl' }
        }
    })

    .state('view2', {
        url: '/view2',
    })

    .state('view3', {
        url: '/view3',
    })

    .state('view4', {
        url: '/view4',
    });
});

可以看出有 4 个主视图(view1、view2、view3、view4),view1 有 3 个子视图。


注入 $httpProvider 的目的是什么?我没有看到它在任何地方使用。
@Aaron app.config 没有以这段代码结尾,可能是 $httpProvider 在其他地方使用
H
Henry Mac

您可以使用 ng-include 来避免使用嵌套的 ng-views。

http://docs.angularjs.org/api/ng/directive/ngInclude
http://plnkr.co/edit/ngdoc:example-example39@snapshot?p=preview

我的索引页使用 ng-view。然后在我需要嵌套框架的子页面上。我使用 ng-include。该演示显示了一个下拉列表。我用链接 ng-click 替换了我的。在函数中我会放 $scope.template = $scope.templates[0];或 $scope.template = $scope.templates[1];

$scope.clickToSomePage= function(){
  $scope.template = $scope.templates[0];
};

A
Adriaan Bouman

Angular ui-router 支持嵌套视图。我还没有使用它,但看起来很有希望。

http://angular-ui.github.io/ui-router/