ホームページ >ウェブフロントエンド >jsチュートリアル >ASP.NET MVC プロジェクトでの RequireJS ライブラリの使用例_JavaScript ヒント

ASP.NET MVC プロジェクトでの RequireJS ライブラリの使用例_JavaScript ヒント

WBOY
WBOYオリジナル
2016-05-16 15:15:331960ブラウズ

RequireJS は、フロントエンドのモジュラー開発用の人気のあるツールであり、require.js という名前の Javascript ライブラリ ファイルです。
RequireJs の主な機能:

(1) Web ページの応答が失われないように、js ファイルの非同期読み込みを実装します。

(2) モジュール間の依存関係を管理して、コードの作成とメンテナンスを容易にします。

フロントエンドのモジュラー開発には多くのツールがあり、一般に 2 つのカテゴリに分類されます。1 つは dojo v1.8 以降の組み込みのモジュラー開発コンポーネントを備えたハイエンド ツールです。 .js が必要です。sea.js はモジュール開発に焦点を当てたツールです。

モジュール分割のルールから、主に AMD と CMD の 2 つのカテゴリに分類されます。Dojo と require.js は前者に従い、sea.js は CMD 仕様に従います。

require は単一ページのアプリケーションでは適切に機能しますが、従来の複数ページのアプリケーションの場合、require の使用はやや混乱し、不便になる可能性があります。

この記事では、ASP.NET MVC の構造に require を適用する方法を説明し、半自動圧縮を実現する圧縮スクリプトを提供します。

別の js コード
一般に、ASP.NET MVC のルートはビューに対応し、ビューのファイル構造は次のようになります。


Views
 |--Shared
 |--_layout.cshtml
 |--Home
 |--Index.cshtml
 |--Blog
 |--Create.cshtml
 |--Edit.cshtml
 |--Detail.cshtml
 |--Index.cshtml
_layout.cshtml は全ページで共有されているものとします。通常の状況では、_layout で jQuery、ブートストラップなどのパブリック js ライブラリを参照するため、他のページがこれらのライブラリを再度参照する必要がなく、コーディング効率が向上します。ただし、異なるページは最終的に異なる js、特にページ自体の機能を実装するカスタム js に依存することになるため、他のページの特別な js を参照するか、次のような js をページ内に直接記述する必要があります。コードはビューによく表示されます:

<script type="text/javascript">
 $(function(){...});
</script>
これにより、ページが混乱し、ページの 3f1c4e4b6b16bbbd69b2ee476dc4f83a タグ内のコードがブラウザーによってキャッシュされなくなり、ページ コードの長さが増加します。さらに重要な欠陥は、jQuery などのライブラリがページに読み込んだ後に匿名関数を実行するため、時間がかかることです。一部のページでは、ページがレイアウト ページとして _layout を使用している限り、jQuery が必要になります。必然的に初期化コードが実行されることになり、無駄です。実際、JavaScript のモジュールローディングのアイデアは、これらの問題を解決することです。

次に、require を使用して js を計画し、次の構造の js ディレクトリを構築します


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
パブリック ライブラリ レベルの js モジュールを js ディレクトリに直接配置し、ページレベルの js をアプリのサブディレクトリに配置します。アプリでは、各ページに js ファイルがあることに注意してください。つまり、各ページの js を抽出する必要があります。これにより、構造が複雑になりますが、ページ内に 3f1c4e4b6b16bbbd69b2ee476dc4f83a タグを記述するという悪い習慣が回避されます。さらに、js ディレクトリ内のパブリック ライブラリには、サードパーティのライブラリに加えて、独自に開発したライブラリも含まれています。このファイルは非常に重要であり、後で説明します。

次に、_layout 内のすべての js 参照を削除し、@RenderSection コマンドを使用して、サブページに js 参照、_layout.cshtml を提供するよう要求します。

<head>
...
@RenderSection("require_js_module", false)
...
</head>
このように、requireの使用方法に応じて、jsの要求が各ビューページに分散され、各サブビューでrequire.jsを参照してメインモジュールを指定する必要があり、これらのメインモジュールは各js

の上のappディレクトリ

@section require_js_module{
 <script src="@Url.Content("~/js/require.js")" data-main="@Url.Content("~/js/app/home.index.js")" ></script>
}
すべての js コードはアプリの js に書き込まれます。これにより、js が標準化され、ページがクリーンになります。さらに重要なのは、これらの js をブラウザーで圧縮してキャッシュすることもでき、実行効率がさらに向上します。

パブリック構成
メイン モジュールは、require メソッドの使用に加えて、require.config を通じて他のモジュールのパスを設定する必要があり、さらに shim も必要になることがわかっています。たとえば、次のコードは、メイン モジュールの先頭に表示されることがよくあります。モジュール:

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

シングルページ アプリケーションの場合、メイン モジュールが 1 つしかないことが多いため、上記のコードは 1 回記述するだけで問題ありません。しかし、複数のページの場合、メインモジュールが複数存在し、それぞれのメインモジュールにそのようなコードが含まれている必要があります。これは非科学的ではありませんか。そこで、統一した設定場所があればいいのですが、どのように書けばよいのでしょうか?これらの設定をモジュール config.js として使用し、次の config.js のように他のメイン モジュールをこのモジュールに依存させることができると考えました。
requirejs.config({
 paths: {
 "jquery": "/js/jquery.min",
 "bootstrap": "/js/bootstrap"
 },
 shim: {
 'bootstrap': {
  deps: ['jquery'],
  exports: "jQuery.fn.popover"
 }
 }
});
config.js の記述方法は特別なことは何もありません。次に、home.index.js の
を引用するだけです。

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

});

ただし、このように書くのはやはり間違いです。メインモジュールが依存するモジュール (ここでは config、jquery、bootstrap) がロードされるとき、ロード順序は不確かですが、config モジュールは前にロードされる必要があるためです。他のモジュール、どうすればいいですか?妥協的な解決策は、home.index.js を次のコードになるように変更することです:

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


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。