国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

在ASP.NET MVC項(xiàng)目中使用RequireJS庫的用法示例

2019-11-20 10:35:55
字體:
供稿:網(wǎng)友

RequireJS 是一個(gè)前端模塊化開發(fā)的流行工具,本身是一個(gè)Javascript的庫文件,即require.js 。
RequireJs的主要功能:

(1)實(shí)現(xiàn)js文件的異步加載,避免網(wǎng)頁失去響應(yīng);

(2)管理模塊之間的依賴性,便于代碼的編寫和維護(hù)。

前端模塊化開發(fā)現(xiàn)在有好多的工具,大體上分為兩類,一類是像dojo之類的高大全,dojo v1.8之后已經(jīng)內(nèi)置了模塊化開發(fā)組件;另一類是像require.js,sea.js 這種專心做模塊化開發(fā)的工具。

從模塊化劃分的規(guī)則來區(qū)分,主要分為AMD、CMD兩類,dojo、require.js 遵從前者,而sea.js 依循CMD規(guī)范。

require在單頁面應(yīng)用中能夠如魚得水,然而對于傳統(tǒng)的多頁面應(yīng)用,使用require多少會(huì)有些困惑和不方便。

本文講解如何在ASP.NET MVC的結(jié)構(gòu)中應(yīng)用require,并且給出了壓縮腳本,實(shí)現(xiàn)半自動(dòng)化壓縮。

將js代碼分離
一般而言ASP.NET MVC的一個(gè)路由對應(yīng)一個(gè)視圖,視圖的文件結(jié)構(gòu)可能如下:


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

這里假設(shè)_layout.cshtml是所有頁面共享的。一般情況下,我們會(huì)在_layout中引用公共的js類庫,比如jQuery,bootstrap等,這樣的話其他的頁面就不需要對這些類庫再引用一遍,提高了編碼的效率。然而,不同的頁面終究會(huì)依賴不同的js,尤其是實(shí)現(xiàn)頁面本身功能的自定義的js,這樣我們不得不在其他頁面中再引用特殊的js,甚至將js直接寫在頁面中,例如下面的代碼經(jīng)常會(huì)出現(xiàn)在View中:

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

這樣會(huì)導(dǎo)致頁面比較混亂,而且頁面<script>標(biāo)簽中代碼不能被瀏覽器緩存,增加了頁面代碼的長度。更為重要的缺陷是,諸如jQuery之類的類庫會(huì)在加載到頁面后執(zhí)行匿名函數(shù),這需要一些時(shí)間,而如果有些頁面根本不需要jQuery的話,只要頁面把_layout作為布局頁面,那么jQuery的初始化代碼將不可避免的執(zhí)行,這是一種浪費(fèi)。事實(shí)上,javascript的模塊化加載的思想就是為了解決這些問題的。

接下來我們來用require規(guī)劃我們的js,構(gòu)建諸如下面結(jié)構(gòu)的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放在一個(gè)app的子目錄下。注意,在app中,每個(gè)頁面一個(gè)js文件,這意味著我們需要把頁面各自的js提取出來,雖然這樣增加了結(jié)構(gòu)復(fù)雜度,但是避免了在頁面中隨手寫<script>標(biāo)簽的陋習(xí)。另外,在js目錄下的公共庫,除了第三方的庫,還包括自己開發(fā)的庫,還有一個(gè)叫config.js的文件,這個(gè)文件很關(guān)鍵,稍后會(huì)說到。

然后,我們可以刪除_layout中所有的js引用,并使用@RenderSection的命令要求子頁面提供js引用,_layout.cshtml:

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

這樣對js的需求就下放到每個(gè)view頁面中了,根據(jù)require的用法,我們需要在各個(gè)子View中引用require.js,并指定主模塊,而這些主模塊就是上面app目錄下的一個(gè)個(gè)js

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

所有的js代碼都將寫到app下的js中,這樣規(guī)范了js,使得頁面更干凈,更為重要的是這些js還可以經(jīng)過壓縮,以及被瀏覽器緩存等,進(jìn)一步提高執(zhí)行效率

公共的config
我們知道主模塊除了使用require方法外,經(jīng)常需要通過require.config來配置其他模塊的路徑,甚至需要shim,例如下面的代碼經(jīng)常會(huì)出現(xiàn)在主模塊的開頭:

require.config({ paths: { "jquery": "lib/jquery.min", "underscore": "lib/underscore.min", "backbone": "lib/backbone.min" }, shim: { 'underscore':{  exports: '_' }, 'backbone': {  deps: ['underscore', 'jquery'],  exports: 'Backbone' } }});
對于單頁面應(yīng)用來說,主模塊往往只有一個(gè),所以上面的代碼寫一遍也就OK了。但是,在多頁面的情況下,主模塊有多個(gè),每個(gè)主模塊都要包含這樣的代碼,豈不是很不科學(xué)?于是,希望有一個(gè)統(tǒng)一配置的地方,但是應(yīng)該如何來寫呢?我們想到,將這些配置作為一個(gè)模塊config.js,讓其他的主模塊對這個(gè)模塊產(chǎn)生依賴就可以了,例如下面的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});

不過這樣寫還是不對的,因?yàn)椋恢髂K依賴的模塊(這里的config,jquery,bootstrap),在加載的時(shí)候,加載順序是不確定的,但是又需要config模塊在其他模塊之前加載,怎么辦呢?一個(gè)折衷的方案是修改home.index.js,成為如下代碼:

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

使用一個(gè)命名的模塊home.index2作為過渡,在主模塊中手動(dòng)require,這樣可以保證config在主模塊執(zhí)行之前加載,也就使得home.index2在加載的時(shí)候已經(jīng)加載了config了。

壓縮
require提供一個(gè)壓縮工具,用于壓縮和合并js,詳情請移步至http://requirejs.org/docs/optimization.html。簡單的說,require提供一個(gè)叫r.js的文件,通過本地的node程序(Node.js),執(zhí)行這個(gè)r.js并傳入一些參數(shù),即可自動(dòng)分析模塊互相之間的依賴,以達(dá)到合并和壓縮的目的。同樣的,這對于單頁面應(yīng)用來說是容易的,因?yàn)橹髂K只有一個(gè),但是對于多頁面又如何做呢?好在這個(gè)壓縮工具支持用一個(gè)配置文件來指導(dǎo)壓縮,這樣的話,我們可以編寫下面的配置腳本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"] }, ... ]}

通過這個(gè)命令來執(zhí)行壓縮,壓縮的結(jié)果將被保存到j(luò)s-build目錄:

node.exe r.js -o build.js

build.js腳本實(shí)際上是一個(gè)js對象,我們將config加入公共模塊,而在各個(gè)主模塊中將其排除。這樣,所有的公共庫包括config將壓縮成一個(gè)js,而主模塊又不會(huì)包含多余的config。這樣可想而知,每個(gè)頁面在加載時(shí)最多只會(huì)下載兩個(gè)js,而且公共模塊的代碼會(huì)“按需執(zhí)行”。

執(zhí)行上面的腳本壓縮,需要安裝有node。可以在從這里下載。

自動(dòng)腳本
但是,隨著主模塊的增加,需要隨時(shí)跟蹤和修改這個(gè)build文件,這也是很麻煩的。于是,筆者基于node.js開發(fā)了一個(gè)叫build-build.js的腳本,用來根據(jù)目錄結(jié)構(gòu)自動(dòng)生成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 objectvar 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); });});

這里的代碼并不復(fù)雜,主要是遍歷目錄,生成對象,最后將對象序列化為build.js。讀者可以自行閱讀并修改。最后,編寫一個(gè)bat,完成一鍵壓縮功能,build.bat:

@echo offset PWD=%~p0set PWD=%PWD:/=/%cd "D:/node"node.exe %PWD%build-build.js build.jsnode.exe %PWD%r.js -o %PWD%build.jscd %~dp0

這樣,我們就簡單實(shí)現(xiàn)了一個(gè)方便的多頁面require方案,最后項(xiàng)目目錄可能是這樣的:

Views |--Shared |--_layout.cshtml |--Home |--Index.cshtml |--Blog |--Create.cshtml |--Edit.cshtml |--Detail.cshtml |--Index.cshtmlbuild|--build.js|--r.js|--build-build.js|--build.batjs|--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


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 白城市| 静海县| 哈尔滨市| 霍州市| 定陶县| 延吉市| 英超| 龙川县| 武川县| 仁化县| 拉萨市| 苗栗县| 陆河县| 来凤县| 舞阳县| 喀喇| 南宫市| 高清| 大关县| 监利县| 绥中县| 日照市| 昌平区| 内黄县| 富平县| 罗山县| 徐水县| 杭锦旗| 宝鸡市| 宝山区| 什邡市| 登封市| 罗江县| 普安县| 白银市| 泗阳县| 满洲里市| 固始县| 齐河县| 云霄县| 龙泉市|