在AngularJS应用程序中使用RequireJS

在编写大型JavaScript应用程序时,最简单的操作之一就是将代码库分成几个文件。 这样做可以提高代码的可维护性,但增加了在主HTML文档中丢失或放错脚本标签的机会。 随着文件数量的增加,跟踪依赖项变得很困难。 这个问题在大型AngularJS应用程序中也仍然存在。 我们有许多工具可用来在应用程序中加载依赖项。

在本文中,我们将看到如何在AngularJS中使用RequireJS来简化加载依赖项的工作。 我们还将研究如何使用Grunt生成包含RequireJS模块的组合文件。

RequireJS简介

RequireJS是一个JavaScript库,可帮助延迟加载JavaScript依赖项。 模块只是其中包含一些RequireJS语法糖的JavaScript文件。 RequireJS实现CommonJS指定的异步模块 。 RequireJS提供了简单的API来创建和引用模块。

RequireJS需要一个主文件,其中包含基本配置数据,例如模块和垫片的路径。 以下代码片段显示了main.js文件的框架:

require.config({
  map:{
    // Maps
  },
  paths:{
    // Aliases and paths of modules
  },
  shim:{
    // Modules and their dependent modules
  }
});

无需在路径部分中指定应用程序中的所有模块。 可以使用它们的相对路径加载其他文件。 要定义模块,我们需要使用define()块。

define([
  // Dependencies
], function(
  // Dependency objects
){

  function myModule() {
    // Can use the dependency objects received above
  }

  return myModule;
});

一个模块可能具有一些从属模块。 通常,对象是在模块末尾返回的,但这不是强制性的。

Angular的依赖注入与RequireJS依赖管理

我从Angular开发人员那里听到的常见问题之一是Angular的依赖管理与RequireJS之间的区别。 重要的是要记住,这两个库的目的完全不同。 AngularJS内置的依赖注入系统处理组件中所需的对象; 而RequireJS中的依赖项管理则处理模块或JavaScript文件。

当RequireJS尝试加载模块时,它将检查所有相关模块并首先加载它们。 缓存已加载模块的对象,并在再次请求相同模块时为它们提供服务。 另一方面,AngularJS维护带有名称和对应对象列表的注入器。 创建组件时,会将条目添加到进样器,并且只要使用注册名称引用该对象,就可以使用该对象。

一起使用RequireJS和AngularJS

本文附带的可下载代码是一个包含两个页面的简单应用程序。 它具有以下外部依赖性:

  • 需求JS
  • jQuery的
  • AngularJS
  • 角线
  • 角资源
  • Angular UI ngGrid

这些文件应按照此处列出的顺序直接加载到页面上。 我们有五个自定义脚本文件,其中包含所需AngularJS组件的代码。 让我们看看如何定义这些文件。

将AngularJS组件定义为RequireJS模块

任何AngularJS组件都包含:

  • 函数定义
  • 依赖注入
  • 注册到Angular模块

在上述三个任务中,我们将在各个模块中执行前两个任务,而第三个任务将在一个单独的模块中执行,该模块负责创建AngularJS模块。

首先,让我们定义一个配置块。 config块不依赖于其他任何块,最后返回config函数。 但是,在将配置模块加载到另一个模块中之前,我们需要加载配置块所需的所有内容。 以下代码包含在config.js

define([],function(){
  function config($routeProvider) {
    $routeProvider.when('/home', {templateUrl: 'templates/home.html', controller: 'ideasHomeController'})
      .when('/details/:id',{templateUrl:'templates/ideaDetails.html', controller:'ideaDetailsController'})
      .otherwise({redirectTo: '/home'});
  }
  config.$inject=['$routeProvider'];

  return config;
});

请注意,以上代码段中执行依赖项注入的方式。 我使用$inject获取$inject的依赖项,因为上面定义的config函数是普通的JavaScript函数。 在关闭模块之前,我们返回config函数,以便可以将其发送到相关模块以供进一步使用。

我们也使用相同的方法来定义任何其他类型的Angular组件,因为这些文件中没有任何组件特定的代码。 以下代码段显示了控制器的定义:

define([], function() {
  function ideasHomeController($scope, ideasDataSvc) {
    $scope.ideaName = 'Todo List';
    $scope.gridOptions = {
      data: 'ideas',
        columnDefs: [
         {field: 'name', displayName: 'Name'},
         {field: 'technologies', displayName: 'Technologies'},
         {field: 'platform', displayName: 'Platforms'},
         {field: 'status', displayName: 'Status'},
         {field: 'devsNeeded', displayName: 'Vacancies'},
         {field: 'id', displayName: 'View Details', cellTemplate: '<a ng-href="#/details/{{row.getProperty(col.field)}}">View Details</a>'}
        ],
        enableColumnResize: true
        };
    ideasDataSvc.allIdeas().then(function(result){
      $scope.ideas=result;
    });
  }

  ideasHomeController.$inject=['$scope','ideasDataSvc'];

  return ideasHomeController;
});

应用程序的Angular模块取决于到目前为止定义的每个模块。 该文件从所有其他文件中获取对象,并将其与AngularJS模块挂钩。 该文件可能会或可能不会返回任何结果,因此可以使用angular.module()从任何地方引用Angular模块。 以下代码块定义了一个Angular模块:

define(['app/config',
  'app/ideasDataSvc',
  'app/ideasHomeController',
  'app/ideaDetailsController'],

  function(config, ideasDataSvc, ideasHomeController, ideaDetailsController){
    var app = angular.module('ideasApp', ['ngRoute','ngResource','ngGrid']);
    app.config(config);
    app.factory('ideasDataSvc',ideasDataSvc);
    app.controller('ideasHomeController', ideasHomeController);
    app.controller('ideaDetailsController',ideaDetailsController);
});

无法使用ng-app指令引导Angular应用ng-app因为所需的脚本文件是异步加载的。 正确的方法是使用手动引导。 这必须在名为main.js的特殊文件中main.js 。 这需要首先定义Angular模块的文件。 该文件的代码如下所示。

require(['app/ideasModule'],
  function() {
    angular.bootstrap(document, ['ideasApp']);
  }
);

配置Grunt以合并RequireJS模块

在部署JavaScript繁重的应用程序时,应将脚本文件合并并缩小以优化脚本文件的下载速度。 诸如Grunt之类的工具可自动完成这些任务。 它定义了许多任务,以简化任何前端部署过程。 它具有grunt-contrib-requirejs任务,用于以正确的顺序组合RequireJS文件模块,然后最小化生成的文件。 与其他繁重的任务一样,可以将其配置为在部署的每个阶段表现不同。 可以在演示应用程序中使用以下配置:

requirejs: {
  options: {
    paths: {
      'appFiles': './app'
    },
    removeCombined: true,
    out: './app/requirejs/appIdeas-combined.js',
    optimize: 'none',
    name: 'main'
  },
  dev:{
    options:{
      optimize:'none'
    }
  },
  release:{
    options:{
      optimize:'uglify'
    }
  }
}

当使用dev选项运行Grunt时,此配置将生成一个未压缩的文件,而当使用release选项运行grunt时,此配置将生成一个最小的文件。

结论

当应用程序的大小超出一定数量的文件时,管理依赖项就变得很困难。 像RequireJS这样的库使定义依赖项变得更加容易,而不必担心文件的加载顺序。 依赖管理正在成为JavaScript应用程序的组成部分。 AngularJS 2.0将内置对AMD的支持。

From: https://www.sitepoint.com/using-requirejs-angularjs-applications/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值