Maison  >  Article  >  interface Web  >  Exemples d'utilisation de la bibliothèque RequireJS dans les conseils de projets ASP.NET MVC_javascript

Exemples d'utilisation de la bibliothèque RequireJS dans les conseils de projets ASP.NET MVC_javascript

WBOY
WBOYoriginal
2016-05-16 15:15:331884parcourir

RequireJS est un outil populaire pour le développement modulaire front-end. Il s'agit d'un fichier de bibliothèque Javascript, à savoir require.js.
Principales fonctions de RequireJs :

(1) Implémenter le chargement asynchrone des fichiers js pour éviter que les pages Web ne perdent de réponse

(2) Gérer les dépendances entre les modules pour faciliter l'écriture et la maintenance du code.

Il existe de nombreux outils pour le développement modulaire front-end, qui sont généralement divisés en deux catégories. L'une est constituée d'outils haut de gamme comme dojo, qui a des composants de développement modulaires intégrés après dojo v1.8 ; nécessitent .js, sea.js est un outil axé sur le développement modulaire.

D'après les règles de division modulaire, il est principalement divisé en deux catégories : AMD et CMD et require.js suivent le premier, tandis que sea.js suit la spécification CMD.

require fonctionne bien dans les applications monopage. Cependant, pour les applications multipages traditionnelles, l'utilisation de require peut être quelque peu déroutante et peu pratique.

Cet article explique comment appliquer require dans la structure d'ASP.NET MVC et fournit un script de compression pour obtenir une compression semi-automatique.

Code js séparé
De manière générale, une route dans ASP.NET MVC correspond à une vue. La structure des fichiers de la vue peut être la suivante :


Views
 |--Shared
 |--_layout.cshtml
 |--Home
 |--Index.cshtml
 |--Blog
 |--Create.cshtml
 |--Edit.cshtml
 |--Detail.cshtml
 |--Index.cshtml

On suppose que _layout.cshtml est partagé par toutes les pages. Dans des circonstances normales, nous référencerons les bibliothèques js publiques dans _layout, telles que jQuery, bootstrap, etc., afin que d'autres pages n'aient pas besoin de référencer à nouveau ces bibliothèques, ce qui améliore l'efficacité du codage. Cependant, différentes pages finiront par s'appuyer sur des js différents, en particulier des js personnalisés qui implémentent les fonctions de la page elle-même, de cette façon, nous devons référencer des js spéciaux dans d'autres pages, ou même écrire des js directement dans la page, comme ce qui suit. le code apparaît souvent dans la vue :

<script type="text/javascript">
 $(function(){...});
</script>

Cela rendra la page confuse et le code dans la balise 3f1c4e4b6b16bbbd69b2ee476dc4f83a de la page ne pourra pas être mis en cache par le navigateur, ce qui augmentera la longueur du code de la page. Le défaut le plus important est que des bibliothèques telles que jQuery exécuteront des fonctions anonymes après leur chargement dans la page, ce qui prend un certain temps. Si certaines pages n'ont pas du tout besoin de jQuery, tant que la page utilise _layout comme page de mise en page, alors jQuery Le le code d'initialisation sera inévitablement exécuté, ce qui est un gaspillage. En fait, l'idée du chargement modulaire de JavaScript est de résoudre ces problèmes.

Ensuite, nous utilisons require pour planifier notre js et créer un répertoire js avec la structure suivante


js
|--app
 |--home.index.js
 |--blog.create.js
 |--blog.edit.js
 |--blog.detail.js
 |--blog.index.js
|--jquery.js
|--bootstrap.js
|--underscore.js
|--jquery.ui.js
|--jquery.customplugin.js
|--config.js
|--require.js

Placez les modules js au niveau de la bibliothèque publique directement dans le répertoire js et placez les js au niveau de la page dans un sous-répertoire d'une application. Notez que dans l'application, chaque page a un fichier js, ce qui signifie que nous devons extraire le js de chaque page. Bien que cela augmente la complexité structurelle, cela évite la mauvaise habitude d'écrire des balises 3f1c4e4b6b16bbbd69b2ee476dc4f83a De plus, les bibliothèques publiques du répertoire js, en plus des bibliothèques tierces, incluent également des bibliothèques auto-développées et un fichier appelé config.js. Ce fichier est très critique et sera discuté plus tard.

Ensuite, nous pouvons supprimer toutes les références js dans _layout et utiliser la commande @RenderSection pour exiger que la sous-page fournisse des références js, _layout.cshtml :

<head>
...
@RenderSection("require_js_module", false)
...
</head>

De cette façon, la demande de js est décentralisée vers chaque page de vue. Selon l'utilisation de require, nous devons référencer require.js dans chaque sous-vue et spécifier le module principal, et ces modules principaux sont dans la. répertoire d'applications au-dessus de chaque js

@section require_js_module{
 <script src="@Url.Content("~/js/require.js")" data-main="@Url.Content("~/js/app/home.index.js")" ></script>
}

Tous les codes js seront écrits en js sous l'application, ce qui standardise les js et rend la page plus propre. Plus important encore, ces js peuvent également être compressés et mis en cache par le navigateur pour améliorer encore l'efficacité de l'exécution.

Configuration publique
Nous savons qu'en plus d'utiliser la méthode require, le module principal a souvent besoin de configurer les chemins des autres modules via require.config, et a même besoin de shim. Par exemple, le code suivant apparaît souvent au début du main. module :

require.config({
 paths: {
 "jquery": "lib/jquery.min",
 "underscore": "lib/underscore.min",
 "backbone": "lib/backbone.min"
 },
 shim: {
 'underscore':{
  exports: '_'
 },
 'backbone': {
  deps: ['underscore', 'jquery'],
  exports: 'Backbone'
 }
 }
});

Pour les applications d'une seule page, il n'y a souvent qu'un seul module principal, il est donc acceptable d'écrire le code ci-dessus une seule fois. Cependant, dans le cas de plusieurs pages, il existe plusieurs modules principaux, et chaque module principal doit contenir un tel code. N'est-ce pas non scientifique ? Donc, j'espère qu'il existe un emplacement de configuration unifié, mais comment dois-je l'écrire ? Nous avons pensé que nous pourrions utiliser ces configurations comme module config.js et laisser d'autres modules principaux dépendre de ce module, comme le config.js suivant :
requirejs.config({
 paths: {
 "jquery": "/js/jquery.min",
 "bootstrap": "/js/bootstrap"
 },
 shim: {
 'bootstrap': {
  deps: ['jquery'],
  exports: "jQuery.fn.popover"
 }
 }
});
Il n'y a rien de spécial dans la façon dont config.js est écrit. Ensuite, citez simplement

dans home.index.js.

require(['../config','jquery', 'bootstrap'], function () {
 //main module code here

});

Cependant, c'est toujours une erreur d'écrire de cette façon, car lorsque les modules dont dépend le module principal (config, jquery, bootstrap ici) sont chargés, l'ordre de chargement est incertain, mais le module de configuration doit être chargé avant autres modules, que faire ? Une solution de compromis consiste à modifier home.index.js pour devenir le code suivant :

require(['../config'], function () {
 require(['home.index2']);
})
, define("home.index2", ['jquery', 'bootstrap'], function () {
 //main module code here
})

使用一个命名的模块home.index2作为过渡,在主模块中手动require,这样可以保证config在主模块执行之前加载,也就使得home.index2在加载的时候已经加载了config了。

压缩
require提供一个压缩工具,用于压缩和合并js,详情请移步至http://requirejs.org/docs/optimization.html。简单的说,require提供一个叫r.js的文件,通过本地的node程序(Node.js),执行这个r.js并传入一些参数,即可自动分析模块互相之间的依赖,以达到合并和压缩的目的。同样的,这对于单页面应用来说是容易的,因为主模块只有一个,但是对于多页面又如何做呢?好在这个压缩工具支持用一个配置文件来指导压缩,这样的话,我们可以编写下面的配置脚本build.js:

var build = {
 appDir: '../js',
 baseUrl: '.',
 dir: '../js-built',
 mainConfigFile: '../js/config.js',
 modules: [
 //First set up the common build layer.
 {
  //module names are relative to baseUrl
  name: 'config',
  //List common dependencies here. Only need to list
  //top level dependencies, "include" will find
  //nested dependencies.
  include: ["bootstrap", "config","jquery"]
 },
 //Now set up a build layer for each page, but exclude
 //the common one. "exclude" will exclude nested
 //the nested, built dependencies from "common". Any
 //"exclude" that includes built modules should be
 //listed before the build layer that wants to exclude it.
 //"include" the appropriate "app/main*" module since by default
 //it will not get added to the build since it is loaded by a nested
 //require in the page*.js files.
 {
 name:"app/home.index",
 exclude:["config"]
 },
 {
 name:"app/blog.create",
 exclude:["config"]
 },
 ...
 ]
}

通过这个命令来执行压缩,压缩的结果将被保存到js-build目录:

node.exe r.js -o build.js

build.js脚本实际上是一个js对象,我们将config加入公共模块,而在各个主模块中将其排除。这样,所有的公共库包括config将压缩成一个js,而主模块又不会包含多余的config。这样可想而知,每个页面在加载时最多只会下载两个js,而且公共模块的代码会“按需执行”。

执行上面的脚本压缩,需要安装有node。可以在从这里下载。

自动脚本
但是,随着主模块的增加,需要随时跟踪和修改这个build文件,这也是很麻烦的。于是,笔者基于node.js开发了一个叫build-build.js的脚本,用来根据目录结构自动生成build.js:

fs = require('fs');
var target_build = process.argv[2];
//console.log(__filename);
var pwd = __dirname;
var js_path = pwd.substring(0,pwd.lastIndexOf('\\')) + '\\js';
console.log('js path : ' + js_path);
var app_path = js_path + '\\app';
console.log('js app path : ' +app_path);

var app_modules = [];
var global_modules = [];

//build json object
var build = {
 appDir: '../js',
 baseUrl: '.',
 dir: '../js-built',
 modules: [
 //First set up the common build layer.
 {
  //module names are relative to baseUrl
  name: 'config',
  //List common dependencies here. Only need to list
  //top level dependencies, "include" will find
  //nested dependencies.
  include: []
 }
 ]
}

fs.readdir(app_path,function (err,files) {
 // body...
 if (err) throw err;
 for(var i in files){
 //put module in app_modules
 var dotindex = files[i].lastIndexOf('.');
 if(dotindex >= 0){
  var extension = files[i].substring(dotindex+1,files[i].length);
  if(extension == 'js'){
  app_modules.push({
   name: 'app/' + files[i].substring(0,dotindex),
   exclude: ['config']
  });
  }
 }
 }

 for(var j in app_modules){
 build.modules.push(app_modules[j]);
 }
 
 fs.readdir(js_path,function (err,files){
 if (err) throw err;
 for(var i in files){
  //put module in app_modules
  var dotindex = files[i].lastIndexOf('.');
  if(dotindex >= 0){
  var extension = files[i].substring(dotindex+1,files[i].length);
  if(extension == 'js'){
   global_modules.push(files[i].substring(0,dotindex));
  }
  } 
 }

 build.modules[0].include = global_modules;
 //console.log(build);
 var t = pwd + '\\' + target_build;
 console.log(t);
 var fd = fs.openSync(t, 'w');
 fs.closeSync(fd);
 var json = JSON.stringify(build);
 fs.writeFileSync(t, json);
 });
});

这里的代码并不复杂,主要是遍历目录,生成对象,最后将对象序列化为build.js。读者可以自行阅读并修改。最后,编写一个bat,完成一键压缩功能,build.bat:

@echo off
set PWD=%~p0
set PWD=%PWD:\=/%
cd "D:\node"
node.exe %PWD%build-build.js build.js
node.exe %PWD%r.js -o %PWD%build.js
cd %~dp0

这样,我们就简单实现了一个方便的多页面require方案,最后项目目录可能是这样的:

Views
 |--Shared
 |--_layout.cshtml
 |--Home
 |--Index.cshtml
 |--Blog
 |--Create.cshtml
 |--Edit.cshtml
 |--Detail.cshtml
 |--Index.cshtml

build
|--build.js
|--r.js
|--build-build.js
|--build.bat

js
|--app
 |--home.index.js
 |--blog.create.js
 |--blog.edit.js
 |--blog.detail.js
 |--blog.index.js
|--jquery.js
|--bootstrap.js
|--underscore.js
|--jquery.ui.js
|--jquery.customplugin.js
|--config.js
|--require.js


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn