7

所以。从前有四种神奇的生物:asp.net mvc、require.js 和 angular。一个聪明的巫师决定把它们放在同一个房子里,让 asp.net 的每个视图都有自己的“代码隐藏”javascript 文件;

首先他添加到_Layout.cshtml

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

然后他main.js在根目录中创建:

require.config({
    baseUrl: "/Scripts/",
    paths: {
        'jquery': 'jquery-1.9.1.min',
        'jquery-ui': 'jquery-ui-1.10.2.custom.min',
        'angular': 'angular.min',
        'ng-grid': 'ng-grid-2.0.2.debug'
    },
    shim: {
        'jquery': { exports: "$" },
        'underscore': { exports: "_" },
        'jquery-ui': ['jquery'],
    },
});
 // Standard Libs
require(['jquery','jquery-ui','underscore','angular']);

还没有什么花哨和神奇的东西。但随后他创建了一个 html 助手:

public static MvcHtmlString RequireJs(this HtmlHelper helper)
{
    var controllerName = helper.ViewContext.RouteData.Values["Controller"].ToString(); // get the controllername 
    var viewName = Regex.Match((helper.ViewContext.View as RazorView).ViewPath, @"(?<=" + controllerName + @"\/)(.*)(?=\.cshtml)").Value; //get the ViewName - extract it from ViewPath by running regex - everything between controllerName +slash+.cshtml should be it;

// chek if file exists
    var filename = helper.ViewContext.RequestContext.HttpContext.Request.MapPath("/Scripts/views/" + controllerName.ToLower() + "-" +
                                                                  viewName.ToLower()+".js");
    if (File.Exists(filename))
    {
        return helper.RequireJs(@"views/" + controllerName.ToLower() + "-" + viewName.ToLower());   
    }
    return new MvcHtmlString("");
}

public static MvcHtmlString RequireJs(this HtmlHelper helper, string module)
{
    var require = new StringBuilder();
    require.AppendLine(" <script type=\"text/javascript\">");
    require.AppendLine("    require(['Scripts/ngcommon'], function() {");
    require.AppendLine("        require( [ \"" + module + "\"] );");
    require.AppendLine("    });");
    require.AppendLine(" </script>");

    return new MvcHtmlString(require.ToString());
}

然后他可以_Layout.cshtml像这样使用它:

   @Html.RequireJs()

如果你仔细听过这个故事,你可能会注意到还有Scripts/ngcommon.js手动引导 angular.js 的文件,并且有常用的 angular 指令和服务

require(['angular', 'jquery'], function() {
    angular.module("common",[]).directive('blabla', function() {
        return {
            restrict: 'A',
            scope: { value: "@blabla" },
            link: function(scope, element, attrs) {     }
        }
    });

    //manually bootstrap it to html body
    $(function(){
        angular.bootstrap(document.getElementsByTagName('body'), ["common"]);
    });
});

神奇的地方来了:从现在开始,如果它是 \Scripts\views 中名为 controllerName-viewName.js 的 javascript 文件,home-index.js对于 Home\Index.cshtml,它将被 require.js 自动拾取并加载。美不美?

但后来魔术师想:如果我需要加载其他东西(比如 ng-grid)并且不应该将某些东西注入到常见的 Angular 模块中,因为并非所有页面都会使用它。当然,他总是可以手动将另一个模块引导到他需要的每个代码隐藏 javascript 中的页面元素中,但他不够聪明地找到问题的答案: 是否可以注入一些 angular.js 组件(如 ng-grid ) 直接进入控制器,而不将其作为应用程序模块的一部分?

4

2 回答 2

1

如果我理解魔术师的想法正确,那么可以通过将您的应用程序拆分为被定义为组件集合的子模块来继续。

myApp如果他为主模块设置依赖项,它将起作用,例如:

var myApp = angular.module('myApp', ['Constants', 'Filters', 'Services', 'Directives', 'Controllers']);
myApp.Constants = angular.module('Constants', []);
myApp.Controllers = angular.module('Controllers', []);
myApp.Filters = angular.module('Filters', []);
myApp.Services = angular.module('Services', []);
myApp.Directives = angular.module('Directives', []);

然后每个子模块:Services等 - 可以使用单个组件进行扩展,例如:

myApp.Controllers.controller('MyController', function () {});
myApp.Services.factory('myService', function () {});
myApp.Directives.directive('myDirective', function () {});
myApp.Filters.filter('myFilter', []);
myApp.Constants.constant('myConstant', []);

这样主应用程序模块加载了几个子模块,但每个结构并不重要。它可以在后端提供的每个页面上包含单独的控制器、服务、指令和过滤器——魔术师只需要确保所有需要的依赖项都已加载。

于 2013-03-28T14:20:25.953 回答
0

DI是在 MVC 视图中具有单独的角度代码隐藏的神奇关键。你甚至根本不需要 requirejs,因为 angular 本质上是一个依赖注入器和模块加载器,angular.bootstrap 是一个神奇的起点。

所以让巫师变得更强大的法术 - $inject

  var TmplController = function($scope, $compile, $http... // any module itself
    {
      this.parts = ['legs','arms','head'];
      $scope.dynamicPageTemplate = function($compile)
      {
        $compile('<div><p ng-repeat="each in parts">{{each}}</p></div>' )( $scope );
      }
    }

  TmplController.$inject = ['$scope','$comple', '$http']; //try legs or head

参考https://github.com/angular/bower-angular-scenario的 angular-scenario.js 的完整注释源,您将了解如何使用定义方式助手注入代码。

于 2013-08-25T23:22:22.430 回答