使用AngularJS / $ controllerProvier和RequireJS

时间:2016-02-14 21:56:53

标签: javascript angularjs requirejs

我从Dan Wahlin那里了解了blog posting关于动态加载控制器和视图的信息。我从github下载了源代码,并试图以较小的比例重现该项目,以了解它是如何工作的。我可以让项目加载视图,但我陷入困境的是弄清楚为什么控制器似乎没有绑定到视图。单步执行代码,我可以看到控制器正在初始化并注入应用程序:

在这里你可以看到应用程序初始化和路由建立

'use strict';

define(['services/routeResolver'], function () {

    var app = angular.module('myApp', ['ngRoute', 'ngAnimate', 'ui.bootstrap', 'breeze.angular', 'routeResolverServices']);

    app.config(['$routeProvider', 'routeResolverProvider', '$controllerProvider',
                '$compileProvider', '$filterProvider', '$provide', '$httpProvider',

     function ($routeProvider, routeResolverProvider, $controllerProvider,
               $compileProvider, $filterProvider, $provide, $httpProvider) {

         app.register = {
             controller: $controllerProvider.register,
             directive: $compileProvider.directive,
             filter: $filterProvider.register,
             factory: $provide.factory,
             service: $provide.service
         };

         //From Dan Whalin project comments: route.resolve() now accepts the convention to use (name of controller & view) as well as the 
         //path where the controller or view lives in the controllers or views folder if it's in a sub folder. 
         // first param is the name of the controller, second param is the directory it and the view exist in, third param is the alias (controller as) optional third param is true false for security 

         var route = routeResolverProvider.route;
         $routeProvider
         .when('/', route.resolve('main', '', 'vm'))
         .otherwise({ redirectTo: '/' });
     }
    ]);

    ////support for lodash
    //   app.factory('_', ['$window', function ($window) {
    //       return $window._;
    //   }]);

    // breeze factory manager
       app.factory('entityManagerFactory', ['breeze', emFactory]);

       function emFactory(breeze) {
           // Convert properties between server-side PascalCase and client-side camelCase
           breeze.NamingConvention.camelCase.setAsDefault();

           // Identify the endpoint for the remote data service
           var serviceRoot = window.location.protocol + '//' + window.location.host + '/';
           var serviceName = serviceRoot + 'breeze/breeze'; // breeze Web API controller

           // the "factory" services exposes two members
           var factory = {
               newManager: function () { return new breeze.EntityManager(serviceName); },
               serviceName: serviceName
           };
           return factory;
       };

       app.service("httpDataLoader", ["$http", function ($http) {
           this.load = function () {
               return $http();
           }
       }]);

    //global filter to allow html to render in the UI and bypass SCE (secure content expression)
    //usage: ng-html-bind="properyExpresson | html"
       app.filter('html', ['$sce', function ($sce) {
           return function (text) {
               return $sce.trustAsHtml(text);
           }
       }
       ]);

    app.run(['breeze', function (breeze) { }]);//currently doing nothing
    return app;
});

更新

有人询问有关路线解析器以及它应该如何工作的问题: 来自Dan Wahlin Bolg:

routeResolver.js脚本创建一个AngularJS提供程序。它由RequireJS加载,并在config()函数中的app.js中用于定义路由并在运行时动态解析它们。

AngularJS已经内置了对动态加载视图的支持,并且还可以动态加载更多的工作控制器。加载控制器脚本可以通过将前面提到的resolve属性分配给处理加载控制器的函数来完成。 routeResolver的独特之处在于它不接受目标视图或控制器的硬编码路径。而是定义一个基本名称,例如“main”,解析器将根据标准约定生成相应视图和控制器的路径。

在main.js中

我定义了要加载的文件

requirejs.config({
    baseUrl: 'app',
    urlArgs: 'v=1.0',
});

require([
    'app',
    'services/routeResolver',
    'services/config',
    'services/dataService'
],
function () {
    angular.bootstrap(document, ['myApp']);
});

在我的mainController中我设置了一个基本的控制器

'use strict';
define(['app'], function (app) {

    var injectParams = ['$window', 'dataService'];

    var mainController = function($window, dataService){

        var vm = this;
        vm.message = 'we are wired up';

        vm.connect = function () {
            alert('hello')
        };
    };

    mainController.$inject = injectParams;
    app.register.controller('mainController', mainController);
});

index.html设置为

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <base href="/">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="Content/bootswatch-slate.css" rel="stylesheet" />
    <title></title>
</head>
<body ng-cloak>
    <div ng-view></div>


    <script src="Scripts/angular.min.js"></script>
    <script src="Scripts/angular-route.min.js"></script>
    <script src="Scripts/angular-animate.min.js"></script>
    <script src="Scripts/angular-sanitize.min.js"></script>
    <script src="Scripts/angular-ui/ui-bootstrap.min.js"></script>
    <script src="Scripts/breeze.min.js"></script>
    <script src="Scripts/breeze.bridge.angular.js"></script>

    <script src="Scripts/require.js" data-main="Scripts/main"></script>
</body>
</html>

主视图非常基本

<div>
    <p>static text</p>
    <p>{{vm.message}}</p>
    <button type="button" ng-click="vm.connect()">click</button>
</div>

我在项目中看到的是页面/视图加载正常,在开发工具中我可以看到控制器以及所有脚本初始化。但是,控制器vm.message或函数调用vm.connect中的作用域项目不会从视图中绑定或识别。开发工具在控制台和静态内容呈现视图中没有显示错误。我想我可能会被控制器的范围所迷惑,要么是重复,要么我不知道是不是正确地注入它。我试图使用Angular扩展来观察范围和监视,但它会出错。当我从gitHub运行源项目时遇到了同样的错误,但是关闭了角度扩展,源项目运行正常。

我尝试设置一个plnkr但是由于项目的配置/路由,它不会从VS运行here is a link to the full solution。如果我需要将代码移到另一个存储库,请将代码放在GoogleDrive共享上,请告知我们。对于我错过或忽略的任何代码审查和建议,我将不胜感激。在将我的代码与Dan的解决方案进行比较时,它似乎是相同的。

我很感激任何建议或想法

感谢

1 个答案:

答案 0 :(得分:0)

博客文章和github中的代码之间存在差异。

博客文章中的routeResolverProvider.route.resolve()仅支持3个参数

function (baseName, path, secure) {...}

在github上,它支持4个参数

function (baseName, path, controllerAs, secure) {...}

因此controllerAs错误注册$routeProvider的唯一可能是使用博客文章中的代码。 routeResolverProvider.route.resolve()不支持controllerAs配置。