Heim >Web-Frontend >js-Tutorial >Anwendungsbeispiele für die Verwendung der RequireJS-Bibliothek in ASP.NET MVC-Projekten_Javascript-Tipps

Anwendungsbeispiele für die Verwendung der RequireJS-Bibliothek in ASP.NET MVC-Projekten_Javascript-Tipps

WBOY
WBOYOriginal
2016-05-16 15:15:331964Durchsuche

RequireJS ist ein beliebtes Tool für die modulare Front-End-Entwicklung. Es handelt sich um eine Javascript-Bibliotheksdatei, nämlich require.js.
Hauptfunktionen von RequireJs:

(1) Implementieren Sie das asynchrone Laden von JS-Dateien, um zu vermeiden, dass Webseiten ihre Reaktion verlieren

(2) Verwalten Sie Abhängigkeiten zwischen Modulen, um das Schreiben und Warten von Code zu erleichtern.

Es gibt viele Tools für die modulare Front-End-Entwicklung, die im Allgemeinen in zwei Kategorien unterteilt sind: Zum einen sind es High-End-Tools wie Dojo, das nach Dojo v1.8 über integrierte modulare Entwicklungskomponenten verfügt erfordern .js, sea.js ist ein Tool, das sich auf die modulare Entwicklung konzentriert.

Nach den Regeln der modularen Aufteilung ist es hauptsächlich in zwei Kategorien unterteilt: AMD und CMD. Require.js folgt der ersteren, während sea.js der CMD-Spezifikation folgt.

require funktioniert gut in einseitigen Anwendungen. Bei herkömmlichen mehrseitigen Anwendungen kann die Verwendung von require jedoch etwas verwirrend und umständlich sein.

In diesem Artikel wird erläutert, wie „require“ in der Struktur von ASP.NET MVC angewendet wird, und es wird ein Komprimierungsskript bereitgestellt, um eine halbautomatische Komprimierung zu erreichen.

Separater js-Code
Im Allgemeinen entspricht eine Route in ASP.NET MVC einer Ansicht. Die Dateistruktur der Ansicht kann wie folgt aussehen:


Views
 |--Shared
 |--_layout.cshtml
 |--Home
 |--Index.cshtml
 |--Blog
 |--Create.cshtml
 |--Edit.cshtml
 |--Detail.cshtml
 |--Index.cshtml
Es wird davon ausgegangen, dass _layout.cshtml von allen Seiten gemeinsam genutzt wird. Unter normalen Umständen verweisen wir in _layout auf öffentliche js-Bibliotheken wie jQuery, Bootstrap usw., sodass andere Seiten nicht erneut auf diese Bibliotheken verweisen müssen, was die Codierungseffizienz verbessert. Allerdings werden verschiedene Seiten irgendwann auf unterschiedliche js angewiesen sein, insbesondere auf benutzerdefinierte js, die die Funktionen der Seite selbst implementieren. Auf diese Weise müssen wir auf spezielle js in anderen Seiten verweisen oder sogar js direkt in die Seite schreiben, wie zum Beispiel die folgende Code erscheint oft in der Ansicht:

<script type="text/javascript">
 $(function(){...});
</script>
Dies führt dazu, dass die Seite unübersichtlich wird und der Code im 3f1c4e4b6b16bbbd69b2ee476dc4f83a-Tag der Seite nicht vom Browser zwischengespeichert werden kann, wodurch sich die Länge des Seitencodes erhöht. Der wichtigere Fehler besteht darin, dass Bibliotheken wie jQuery nach dem Laden auf der Seite anonyme Funktionen ausführen, was einige Zeit in Anspruch nimmt. Wenn einige Seiten überhaupt kein jQuery benötigen, solange die Seite _layout als Layoutseite verwendet, dann jQuery Der Initialisierungscode wird zwangsläufig ausgeführt, was eine Verschwendung darstellt. Tatsächlich besteht die Idee des modularen Ladens von JavaScript darin, diese Probleme zu lösen.

Als nächstes verwenden wir require, um unser JS zu planen und ein JS-Verzeichnis mit der folgenden Struktur zu erstellen


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
Legen Sie JS-Module auf öffentlicher Bibliotheksebene direkt im JS-Verzeichnis ab und platzieren Sie JS-Module auf Seitenebene in einem Unterverzeichnis einer App. Beachten Sie, dass in der App jede Seite eine js-Datei hat, was bedeutet, dass wir die js jeder Seite extrahieren müssen. Dies erhöht zwar die strukturelle Komplexität, vermeidet jedoch die schlechte Angewohnheit, 3f1c4e4b6b16bbbd69b2ee476dc4f83a Darüber hinaus enthalten die öffentlichen Bibliotheken im js-Verzeichnis neben Bibliotheken von Drittanbietern auch selbst entwickelte Bibliotheken und eine Datei namens config.js. Diese Datei ist sehr wichtig und wird später besprochen.

Dann können wir alle JS-Referenzen in _layout löschen und den Befehl @RenderSection verwenden, um von der Unterseite die Bereitstellung von JS-Referenzen zu verlangen, _layout.cshtml:

<head>
...
@RenderSection("require_js_module", false)
...
</head>
Auf diese Weise wird die Nachfrage nach js dezentral auf jede Ansichtsseite verteilt. Entsprechend der Verwendung von require müssen wir in jeder Unteransicht auf require.js verweisen und das Hauptmodul angeben, und diese Hauptmodule befinden sich in der App-Verzeichnis oben Jedes js

@section require_js_module{
 <script src="@Url.Content("~/js/require.js")" data-main="@Url.Content("~/js/app/home.index.js")" ></script>
}
Alle JS-Codes werden in JS unter der App geschrieben, was JS standardisiert und die Seite sauberer macht. Noch wichtiger ist, dass diese JS auch vom Browser komprimiert und zwischengespeichert werden können, um die Ausführungseffizienz weiter zu verbessern

Öffentliche Konfiguration

Wir wissen, dass das Hauptmodul zusätzlich zur Verwendung der Methode „require“ häufig die Pfade anderer Module über „require.config“ konfigurieren muss und sogar Shim benötigt. Beispielsweise erscheint der folgende Code häufig am Anfang des Hauptmoduls Modul:

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

Bei einseitigen Anwendungen gibt es oft nur ein Hauptmodul, daher ist es in Ordnung, den obigen Code einmal zu schreiben. Bei mehreren Seiten gibt es jedoch mehrere Hauptmodule, und jedes Hauptmodul muss solchen Code enthalten. Ist das nicht unwissenschaftlich? Ich hoffe also, dass es einen einheitlichen Konfigurationsort gibt, aber wie soll ich ihn schreiben? Wir dachten, wir könnten diese Konfigurationen als Modul config.js verwenden und andere Hauptmodule von diesem Modul abhängig machen, wie zum Beispiel die folgenden config.js:
requirejs.config({
 paths: {
 "jquery": "/js/jquery.min",
 "bootstrap": "/js/bootstrap"
 },
 shim: {
 'bootstrap': {
  deps: ['jquery'],
  exports: "jQuery.fn.popover"
 }
 }
});
Es gibt nichts Besonderes an der Art und Weise, wie config.js geschrieben ist. Als nächstes zitieren Sie einfach
in home.index.js

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

});

Es ist jedoch immer noch falsch, so zu schreiben, denn wenn die Module geladen werden, von denen das Hauptmodul abhängt (hier config, jquery, Bootstrap), ist die Ladereihenfolge ungewiss, aber das Konfigurationsmodul muss vorher geladen werden andere Module, was tun? Eine Kompromisslösung besteht darin, home.index.js so zu ändern, dass der folgende Code entsteht:

使用一个命名的模块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


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn