8

我有一个需要加载单独的角度应用程序的用例。

基于几个堆栈溢出问题和这个谷歌线程,它是可行的。但是,我无法让它工作。

查看文档:

http://docs.angularjs.org/api/angular.bootstrap

看起来您需要提供元素(获取元素句柄的正确方法是什么?),然后如何将其绑定回配置、控制器等。这将如何与路由一起使用?IE 碰撞是如何工作的,即应用程序 a 和应用程序 b 分别将 /foo 映射到 /fooa.html 和 /foob.html...或者每个应用程序都描述了自己的 .otherwise?

谢谢!

4

4 回答 4

8

因此,考虑到这是一个服务驱动的内容的要求,我能看到的唯一方法是混合 Angular 和标准 html 实践。实际上,您需要从 plunker book 中获取一个页面并使用 iframe 来包含每个单独的 portlet。

<!doctype html> <html lang="en">

<body ng-app="plunker" ng-controller="MainCtrl">

<!-- define foo -->

<div>
    <ul class="menu">
        <li><a href="#" ng-click="fooRoute='#/foo1'">foo1</a></li>
        <li><a href="#" ng-click="fooRoute='#/foo2'">foo2</a></li>
    </ul>
    <iframe seamless="true" ng-src="foo.index.html{{fooRoute}}"></iframe> </div>

<div>
    <ul class="menu">
        <li><a href="#" ng-click="barRoute='#/bar1'">bar1</a></li>
        <li><a href="#" ng-click="barRoute='#/bar2'">bar2</a></li>
    </ul>
    <iframe seamless="true" ng-src="bar.index.html{{barRoute}}"></iframe> </div>


<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script> <script src="app.js"></script> </body> </html>

然后在这些portlet 中的每一个上,您都希望拥有一个完全独立的应用程序(包括资源的加载)。

<!doctype html>
<html lang="en">

<body ng-app="fooApp">

<div ng-view></div>


<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
<script>
  var app = angular.module('fooApp', ['fooApp.controllers']);

    // Configure the app
    app.config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/foo1', {template: '<h1>Foo</h1><h2>foo1</h2>', controller: 'MyCtrl1'});
        $routeProvider.when('/foo2', {template: '<h1>Foo</h1><h2>foo2</h2>', controller: 'MyCtrl2'});
    }]);

    angular.module('fooApp.controllers', []).
            controller('MyCtrl1', [function () {
                console.log("fooApp.MyCtrl1 invoked.");
            }])
            .controller('MyCtrl2', [function () {
                console.log("fooApp.MyCtrl2 invoked.");
            }]);
</script>
</body>
</html>

与使用通用应用程序库相比,这对于加载的效率要低一些,但目前这是不可行的。angular-ui 的 ui-router 团队中有关于控制独立视图的讨论,这对您来说可能是一个可行的解决方案,但目前尚未实现,您可以关注https://github.com/angular-ui/ui的讨论-router/issues/84并满足您的需求。现在在https://github.com/angular-ui/ui-router/issues/160的 ui-router 问题列表中也有一个专门针对此的问题。

此设计的工作 plunker:http ://plnkr.co/edit/sPoK3I?p=preview

于 2013-06-01T13:36:16.653 回答
2

好的,所以我想出了如何使用 angular ui-router 来做到这一点,关键归结为 angular ui-router 在不影响 URL 的情况下转换状态的能力。

使其工作的步骤

  • 首先将每个应用程序实例化为一个独立的应用程序,使用手动引导到一个 ID 元素。
  • 将 ui-router $stateProvider 附加到每个应用程序以驱动内部状态转换(路由)。
    • 您必须在此处为每个定义的状态保留 url 键,否则您将通过更改每个状态转换的 url 来重置页面。
  • 在主控制器中设置状态函数以驱动状态变化。

以下是使其工作的代码:

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.0.x" src="http://code.angularjs.org/1.0.7/angular.min.js" data-semver="1.0.7"></script>
    <script src="angular-ui-states.min.js"></script>
    <script src="app.js"></script>
  </head>
<!-- define foo -->

<div id="fooApp" ng-controller="MainCtrl">

    <ul class="menu">
        <li><a href="#" ng-click="state('foo1')">foo1</a></li>
        <li><a href="#" ng-click="state('foo2')">foo2</a></li>
    </ul>
    <div ui-view>
    </div>

</div>

<script>
    // Declare app level module which depends on filters, and services
    var app = angular.module('fooApp', ['fooApp.controllers', 'ui.state']);

    // Configure the app
    app.config(['$stateProvider', function ($stateProvider) {
        $stateProvider
          .state('foo1',
          {
            template: '<h1>Foo</h1><h2>foo1</h2>', 
            controller: 'MyCtrl1'
          })
          .state('foo2',
          {
            template: '<h1>Foo</h1><h2>foo2</h2>', 
            controller: 'MyCtrl2'
          });
    }]);

    angular.module('fooApp.controllers', [])
            .controller('MainCtrl', ['$scope', '$state', function($scope, $state){
              $scope.state = function(name){
                console.log('Transition to state ' + name);
                $state.transitionTo(name);
              }
            }])
            .controller('MyCtrl1', [function () {
                console.log("fooApp.MyCtrl1 invoked.");
            }])
            .controller('MyCtrl2', [function () {
                console.log("fooApp.MyCtrl2 invoked.");
            }]);

    // manually bootstrap
    var div = document.getElementById('fooApp');
    console.log(div);
    angular.bootstrap(div, ['fooApp']);


</script>


<!-- define bar -->

<div id="barApp" ng-controller="MainCtrl">

    <ul class="menu">
        <li><a href="#" ng-click="state('bar1')">bar1</a></li>
        <li><a href="#" ng-click="state('bar2')">bar2</a></li>
    </ul>
    <div ui-view>
    </div>

</div>

<script>
    // Declare app level module which depends on filters, and services
    var app = angular.module('barApp', ['barApp.controllers', 'ui.state']);


    app.config(['$stateProvider', function ($stateProvider) {
        $stateProvider
          .state('bar1',
          {
            template: '<h1>Bar</h1><h2>bar1</h2>', 
            controller: 'MyCtrl1'
          })
          .state('bar2',
          {
            template: '<h1>Bar</h1><h2>bar2</h2>', 
            controller: 'MyCtrl2'
          });
    }]);

    angular.module('barApp.controllers', [])
            .controller('MainCtrl', ['$scope', '$state', function($scope, $state){
              $scope.state = function(name){
                console.log('Transition to state ' + name);
                $state.transitionTo(name);
              }
            }])
            .controller('MyCtrl1', [function () {
                console.log("barApp.MyCtrl1 invoked.");
            }])
            .controller('MyCtrl2', [function () {
                console.log("barApp.MyCtrl2 invoked.");
            }]);

    // manually bootstrap
    var div = document.getElementById('barApp');
    console.log(div);
    angular.bootstrap(div, ['barApp']);
</script>


</body>

</html>

此解决方案的工作 plunker 在http://plnkr.co/edit/bXSN8qSMdioZJLYs2zyk?p=preview

请参阅我之前的回答,了解当前正在进行的讨论,以使 ui-router 中的 portlet 支持更加内在。

于 2013-06-04T17:59:47.447 回答
1

弄清楚了。以下是如何成功并行加载两个角度应用程序。另请参阅我为每个应用程序命名了相同的控制器,以表明依赖关系不会发生冲突(因为它们通过模块在每个相应的应用程序内限定):

<!doctype html>
<html lang="en">

<body>

<script src="lib/angular/angular.js"></script>

<!-- define foo -->

<div id="fooApp">

    <ul class="menu">
        <li><a href="#/foo1">foo1</a></li>
        <li><a href="#/foo2">foo2</a></li>
    </ul>
    <div ng-view>
    </div>

</div>

<script>
    // Declare app level module which depends on filters, and services
    var app = angular.module('fooApp', ['fooApp.controllers']);

    // Configure the app
    app.config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/foo1', {template: '<h1>Foo</h1><h2>foo1</h2>', controller: 'MyCtrl1'});
        $routeProvider.when('/foo2', {template: '<h1>Foo</h1><h2>foo2</h2>', controller: 'MyCtrl2'});
    }]);

    angular.module('fooApp.controllers', []).
            controller('MyCtrl1', [function () {
                console.log("fooApp.MyCtrl1 invoked.");
            }])
            .controller('MyCtrl2', [function () {
                console.log("fooApp.MyCtrl2 invoked.");
            }]);

    // manually bootstrap
    var div = document.getElementById('fooApp');
    console.log(div);
    angular.bootstrap(div, ['fooApp']);


</script>


<!-- define bar -->

<div id="barApp">

    <ul class="menu">
        <li><a href="#/bar1">bar1</a></li>
        <li><a href="#/bar2">bar2</a></li>
    </ul>
    <div ng-view>
    </div>

</div>

<script>
    // Declare app level module which depends on filters, and services
    var app = angular.module('barApp', ['barApp.controllers']);

    // Configure the app
    app.config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/bar1', {template: '<h1>Bar</h1><h2>bar1</h2>', controller: 'MyCtrl1'});
        $routeProvider.when('/bar2', {template: '<h1>Bar</h1><h2>bar2</h2>', controller: 'MyCtrl2'});
    }]);

    angular.module('barApp.controllers', []).
            controller('MyCtrl1', [function () {
                console.log("barApp.MyCtrl1 invoked.");
            }])
            .controller('MyCtrl2', [function () {
                console.log("barApp.MyCtrl2 invoked.");
            }]);


    // manually bootstrap
    var div = document.getElementById('barApp');
    console.log(div);
    angular.bootstrap(div, ['barApp']);
</script>


</body>

</html>

剩下的唯一问题是如何处理路由冲突。

于 2013-05-31T21:17:32.510 回答
0

好吧,您在这里有两个选择:如果您将它们创建为angular.module(),则无法通过 atm 将模块相互连接。

如果您使用templateURL创建指令来延迟加载您的组件,您可以广播共享属性并收听它们您可以在您的应用程序中使用相同的服务。可能这对你来说是最好的。

于 2013-05-24T14:26:56.220 回答