日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Unobtrusive JavaScript介绍

發布時間:2023/12/15 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unobtrusive JavaScript介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Unobtrusive JavaScript介紹

??

原文: http://blog.csdn.net/peterinor_/article/details/16367935?


在asp.net MVC開發框架中,MS一直使用其開發的Unobtrusive JavaScript

1. ?Unobtrusive JavaScript介紹

說到Unobtrusive Ajax,就要談談UnobtrusiveJavaScript了,所謂Unobtrusive JavaScript即為非侵入式JavaScript,是目前在Web開發領域推行的一種思想。

相信大家一定都有直接在HTMLElements上面寫上事件調用代碼的情況,比如:

[html] view plaincopy
  • <!--page.html-->??
  • <!doctype?html>??
  • <html>??
  • <head>??
  • ????<title>Obtrusive?JavaScript?Page</title>??
  • ????<script?type="text/ecmascript">??
  • ????????function?onload()?{??
  • ????????????console.log("Page?has?be?loaded");??
  • ????????}??
  • ????</script>??
  • </head>??
  • <body?onload="onload">??
  • ????<button?onclick="alert('hello');">Hello</button>??
  • ????<div?onclick="this.style.color='red'">??
  • ????????Click?to?Change?Color??
  • ????</div>??
  • </body>??
  • </html>??

  • 這種代碼就叫做侵入式的JavaScript,因為這種情況下JavaScript代碼和HTML代碼混在在一起,不利于代碼閱讀以及然后維護,還會導致HTML代碼混亂不堪。

    而相對與上面的做法,非侵入式JavaScript則采用如下的做法來避免這種混亂:

    [html] view plaincopy
  • <!--page.html-->??
  • <!doctype?html>??
  • <html>??
  • <head>??
  • ????<title>Unobtrusive?JavaScript?Page</title>??
  • ????<script?src="page.js"></script>??
  • </head>??
  • <body>??
  • ????<button?id="btnHello">Hello</button>??
  • ????<div?id="colorChg">??
  • ????????Click?to?Change?Color??
  • ????</div>??
  • </body>??
  • </html>??
  • [javascript] view plaincopy
  • //page.js??
  • document.onload?=?function?(e)?{??
  • ????var?body?=?document.getElementsByTagName('body')[0];??
  • ????body.onload?=?function(e)?{??
  • ????????console.log("Page?has?be?loaded");??
  • ????}??
  • ??
  • ????var?btn?=?document.getElementById('btnHello');??
  • ????btn.onclick?=?function?(e)?{??
  • ????????alert('hello');??
  • ????}??
  • ??
  • ????var?div?=?document.getElementById('colorChg');??
  • ????div.onclick?=?function?(e)?{??
  • ????????this.style.color?=?'red';??
  • ????}??
  • };??

  • 當然,為了讓JavaScript看起來更加的優美,寫起來更加的舒暢,更加的不那么費勁,可以使用現成的JavaScript類庫完成上面的操作,比如jQuery:

    [javascript] view plaincopy
  • //page.js??
  • $(function?(e)?{??
  • ????$('body').click(function?(e)?{??
  • ????????console.log("Page?has?be?loaded");??
  • ????});??
  • ????$('#btnHello').click(function?(e)?{??
  • ????????alert('hello');??
  • ????});??
  • ????$('#colorChg').click(function?(e)?{??
  • ????????$(this).css('color',?'red');??
  • ????});??
  • });??

  • 2.? Unobtrusive JavaScript在ASP.NET MVC中的應用

    使用VS新建一個ASP.NET MVC項目就會在~/Scripts/目錄下面看到很多以unobtrusive結尾的javascript腳本文件,如:


    今天的主角是ASP.NET MVC Unobtrusive Ajax,那么大家應該可以猜到主要還是jquery.unobtrusive-ajax.js和jquery.unobtrusive-ajax.min.js這兩個文件。這就是ASP.NETMVC實現非侵入式Ajax的主要手段,若要在項目中使用Unobtrusive Ajax,那么一定要用到這兩個文件中的一個,至于具體用哪個就不多廢話了。下面來看看Unobtrusive Ajax在ASP.NET MVC中的使用。

    ASP.NET MVC中使用Unobtrusive Ajax主要用到的是Ajax輔助方法,這些方法由AjaxHelper提供,定義在System.Web.Mvc.Ajax.AjaxExtensions類中。Ajax主要用到的方法有ActionLinkRouteLinkBeginFormBeginRouteForm,當然這些方法都有各自重載的版本,具體參見MSDN文檔,本文主要以具有代表性的BeginForm為例來進行說明,其他的用法大同小異。

    ASP.NET MVC對BeginForm的使用提供了11個重載的版本,但是細細觀察11個重載版本就會發現,這些重載中共同點是有一個AjaxOptions類型的參數,除此之外Ajax輔助方法的BeginForm和Html輔助方法的BeginForm相同參數版本之間并無差別,而這個AjaxOptions就是ASP.NET MVC實現Ajax方法依據。

    為了便于觀察測試效果,在新建的MVC項目的HomeController中增加如下Action:

    [csharp] view plaincopy
  • public?ActionResult?Index()??
  • {??
  • ????return?View();??
  • }??
  • public?string?s(string?q)??
  • {??
  • ????return?"The?Query?String?is?:?"?+?q;??
  • }??

  • 其中Action ‘Index’用于顯示Ajax操作頁面,Action ‘s’用來響應Ajax請求結果。Index頁面的主要內容如下:

    [html] view plaincopy
  • @using?(Ajax.BeginForm(??
  • ????new?AjaxOptions??
  • ????{??
  • ????????Url?=?"Home/s",??
  • ????????HttpMethod?=?"GET",??
  • ????????UpdateTargetId?=?"searchResult",??
  • ????????InsertionMode?=?InsertionMode.Replace??
  • ????}))??
  • {??
  • ????<input?type="text"?name="q"?/>??
  • ????<input?type="submit"?value="查詢"?/>??
  • }??
  • <div?id="searchResult"></div>??
  • 其作用就是生成一個表單,提交這個表單的時候執行異步的Ajax請求,并將請求結果回顯到id為searchResult的div元素內。運行如下:


    此處只用到了AjaxOptions的四個屬性,AjaxOptions的其他屬性如下表所示:


    各個參數的具體意思都已經有解釋了,深入的用法將在本文第三部分予以說明。上表中對參數進行了分組和著色以示區分其在BeginForm中的作用:前兩個Url和HttpMethod算是Ajax請求的基礎了,指示了Ajax請求的Url路徑及所采用的Http方法;UpdateTargetId和InsertionMode是對請求成功后回顯的設置,正如上例所示的那樣;OnBegin、OnComplete、OnFailure以及OnSuccess四個屬性則是對Ajax請求過程JavaScript回調的設置,具體是什么大家可望文生義了,這些值可以是具體的JavaScript語句或者是一個JavaScript函數;而Confirm則是在發起Ajax請求前頁面進行確認的消息,頁面通過window.confirm顯示確認信息;最后,LoadingElementDuration和LoadingElementId這兩個則屬于錦上添花的東西了,用于在請求過程中顯示頁面動態請求情況,比如一個‘Loading…’的文字或者一個顯示進度的圖片。

    ?

    下面是一個完整的例子:

    [html] view plaincopy
  • @using?(Ajax.BeginForm(??
  • ????new?AjaxOptions??
  • ????{??
  • ????????Url?=?"Home/s",??
  • ????????HttpMethod?=?"GET",??
  • ????????UpdateTargetId?=?"searchResult",??
  • ????????InsertionMode?=?InsertionMode.Replace,??
  • ????????OnBegin?=?"alert('開始請求');",??
  • ????????OnComplete?=?"Ajax.GetData_Com",??
  • ????????OnSuccess?=?"alert('請求成功');",??
  • ????????OnFailure?=?"alert('請求失敗');",??
  • ????????Confirm?=?"確認發起搜索",??
  • ????????LoadingElementDuration?=?500,??
  • ????????LoadingElementId?=?"waiting"??
  • ????}))??
  • {??
  • ????<input?type="text"?name="q"?/>??
  • ????<input?type="submit"?value="查詢"?/>??
  • ????<span?id="waiting"?style="display:?none">Loading...</span>??
  • }??
  • <div?id="searchResult"></div>??
  • ??
  • <script>??
  • ????Ajax?=?{};??
  • ????Ajax.GetData_Com?=?function?(data,?status,?xhr)?{??
  • ????????console.log(data);??
  • ????};??
  • </script>??
  • 當然,真正的Unobtrusive自然是要將下面的腳本單獨放到一個js文件中的,此處為了示例就免去這個麻煩了^_^。


    3.? ASP.NET MVC Unobtrusive Ajax原理剖析

    看看上面的Ajax輔助方法,的確給設計帶來了不小的便利和幫助,省去了很多手工使用$.ajax或者$.get或者$.post的不便,那么這種便利是怎么實現的,鄙人有一毛病,遇到問題總要刨根問題搞個清楚。下面權當是自己分析的一些心得,與大家分享,不善之處,還望不吝賜教。

    前面說到ASP.NET MVC實現Unobtrusive Ajax主要使用的是jquery.unobtrusive-ajax.js這個JavaScript腳本,這個當然是首先要看的嘍。可是打開文件發現里面有不少類似data-ajax-*這樣的Html屬性,接觸過HTML5的筒子們都應該知道這是HTML5預留給用戶程序使用的屬性,這自然是和Html相關,看來有必要看看Ajax.BeginForm輔助方法生成的Html代碼哦。

    原諒我還拿前面的例子,Razor引擎生成的Html腳本如下(原諒我為了便于閱讀做了稍微的調整):

    [html] view plaincopy
  • <form?action="/"???
  • ????data-ajax="true"???
  • ????data-ajax-url="Home/s"??
  • ????data-ajax-method="GET"???
  • ????data-ajax-begin="alert('開始請求');"??
  • ????data-ajax-complete="Ajax.GetData_Com"???
  • ????data-ajax-update="#searchResult"???
  • ????data-ajax-mode="replace"???
  • ????data-ajax-success="alert('請求成功');"???
  • ????data-ajax-failure="alert('請求失敗');"???
  • ????data-ajax-confirm="確認發起搜索"???
  • ????data-ajax-loading="#waiting"???
  • ????data-ajax-loading-duration="500"???
  • ????method="post">??????
  • ????<input?type="text"?name="q"?/>??
  • ????<input?type="submit"?value="查詢"?/>??
  • ????<span?id="waiting"?style="display:?none">Loading...</span>??
  • </form>??
  • <div?id="searchResult"></div>??
  • ??
  • <script>??
  • ????Ajax?=?{};??
  • ????Ajax.GetData_Com?=?function?(data,?status,?xhr)?{??
  • ????????console.log(data);??
  • ????};??
  • </script>??
  • 可見,Ajax.BeginForm輔助方法的確為表單添加了很多以data-ajax-開頭的屬性,你一定想到了,這些屬性的生成肯定和AjaxOptions有關,Bingo,對應關系如下表:

    可以說,ASP.NET MVC實現一個Unobtrusive Ajax所需的全部東西都在這里了。下面就來分析一下jquery.unobtrusive-ajax.js中的實現機制。

    回想一下,通過jQuery發起一個Ajax請求的過程,ASP.NET MVC實現Unobtrusive Ajax則是基于jQuery的,你一定猜到了,這個過程的核心就是一次$.ajax()調用!!而如你所知,$.ajax()的調用其實也就是準備一個ajaxOptions!!

    ASP.NET MVC完成這一過程的核心有兩步:

    • 截獲<form>的submit事件或者<a>的click事件,并獲取Ajax.BeginForm或者Ajax.BeginRouteForm或者Ajax.ActionLink或者Ajax.RouteLink中設置AjaxOptions屬性(這些屬性分別對應類似data-ajax-*的html5屬性,見上面表格),并通過這些屬性設定$.ajax()調用所需的ajaxOptions。
    • 通過前面的ajaxOptions發起$.ajax()調用,完成Ajax請求。

    jquery.unobtrusive-ajax.js中與此過程涉及的主要有兩段代碼(其他的代碼都是輔助性代碼,都為這兩個服務)。

    第一段在jquery.unobtrusive-ajax.js文件的最后面,如下:

    ??? 代碼段一:

    [javascript] view plaincopy
  • $("form[data-ajax=true]").live("submit",?function?(evt)?{??
  • ????var?clickInfo?=?$(this).data(data_click)?||?[];??
  • ????evt.preventDefault();??
  • ????if?(!validate(this))?{??
  • ????????return;??
  • ????}??
  • ????asyncRequest(this,?{??
  • ????????url:?this.action,??
  • ????????type:?this.method?||?"GET",??
  • ????????data:?clickInfo.concat($(this).serializeArray())??
  • ????});??
  • });??


  • 或(注意是或)

    [javascript] view plaincopy
  • $("a[data-ajax=true]").live("click",?function?(evt)?{??
  • ????evt.preventDefault();??
  • ????asyncRequest(this,?{??
  • ????????url:?this.href,??
  • ????????type:?"GET",??
  • ????????data:?[]??
  • ????});??
  • });??

  • 作為jQuery的專家,你一定一眼就能看出此段代碼的意圖,對,監控頁面中所有具有data-ajax屬性的表單的提交操作,此處用的是$.live()方法(關于$.live就不廢話了),這就是頁面中不需要手工再去截獲表單的submit事件或者鏈接的click事件的原因所在!

    第二段就是第一段中出現的asyncRequest()函數,該函數中有兩處代碼,大家一看就會明白整個Ajax請求發起的過程了:

    ??? 代碼段二:

    [javascript] view plaincopy
  • function?asyncRequest(element,?options)?{??
  • ????var?confirm,?loading,?method,?duration;??
  • ??
  • ????confirm?=?element.getAttribute("data-ajax-confirm");??
  • ????if?(confirm?&&?!window.confirm(confirm))?{??
  • ????????return;??
  • ????}??
  • ??
  • ????loading?=?$(element.getAttribute("data-ajax-loading"));??
  • ????duration?=?element.getAttribute("data-ajax-loading-duration")?||?0;??
  • ??
  • ????$.extend(options,?{??
  • ????????type:?element.getAttribute("data-ajax-method")?||?undefined,??
  • ????????url:?element.getAttribute("data-ajax-url")?||?undefined,??
  • ????????beforeSend:?function?(xhr)?{??
  • ????????????var?result;??
  • ????????????asyncOnBeforeSend(xhr,?method);??
  • ????????????result?=?getFunction(element.getAttribute("data-ajax-begin"),?["xhr"]).apply(this,?arguments);??
  • ????????????if?(result?!==?false)?{??
  • ????????????????loading.show(duration);??
  • ????????????}??
  • ????????????return?result;??
  • ????????},??
  • ????????complete:?function?()?{??
  • ????????????loading.hide(duration);??
  • ????????????getFunction(element.getAttribute("data-ajax-complete"),?["xhr",?"status"]).apply(this,?arguments);??
  • ????????},??
  • ????????success:?function?(data,?status,?xhr)?{??
  • ????????????asyncOnSuccess(element,?data,?xhr.getResponseHeader("Content-Type")?||?"text/html");??
  • ????????????getFunction(element.getAttribute("data-ajax-success"),?["data",?"status",?"xhr"]).apply(this,?arguments);??
  • ????????},??
  • ????????error:?getFunction(element.getAttribute("data-ajax-failure"),?["xhr",?"status",?"error"])??
  • ????});??
  • ??
  • ????options.data.push({?name:?"X-Requested-With",?value:?"XMLHttpRequest"?});??
  • ??
  • ????method?=?options.type.toUpperCase();??
  • ????if?(!isMethodProxySafe(method))?{??
  • ????????options.type?=?"POST";??
  • ????????options.data.push({?name:?"X-HTTP-Method-Override",?value:?method?});??
  • ????}??
  • ??
  • ????$.ajax(options);??
  • }??

  • 沒錯,這兩段就完成ASP.NET MVC 的Ajax請求。而從這兩段代碼中你也一定大致看出了前面的OnBegin、OnComplete、OnFailure以及OnSuccess四個屬性對應的Ajax請求過程JavaScript回調對應的是Ajax請求的哪個部分了:


    這里有一個關鍵的函數地方‘getFunction’,它定義在jquery.unobtrusive-ajax.js文件的最前面:

    [javascript] view plaincopy
  • function?getFunction(code,?argNames)?{??
  • ????var?fn?=?window,?parts?=?(code?||?"").split(".");??
  • ????while?(fn?&&?parts.length)?{??
  • ????????fn?=?fn[parts.shift()];??
  • ????}??
  • ????if?(typeof?(fn)?===?"function")?{??
  • ????????return?fn;??
  • ????}??
  • ????argNames.push(code);??
  • ????return?Function.constructor.apply(null,?argNames);??
  • }??

  • 這個函數的功能就是從data-ajax-*中和JavaScript回調相關的屬性中獲取JavaScript回調函數。拿OnComplete來說,通過Html ElementgetAttribute("data-ajax-complete")獲取data-ajax-complete屬性(設為oncomplete),首先假設oncomplete為定義在外部JavaScript腳本文件中的函數,然后一級一級的查找該函數,回到前面例子里面對AjaxOptions的設定OnComplete = "Ajax.GetData_Com",那么,此處getFunction函數將返回的是window.Ajax.GetData_Com這個函數(注意window是JavaScript默認的全局名稱空間),那么請求完成后,window.Ajax.GetData_Com將會被調用,即:

    window.Ajax.GetData_Com.apply(this, arguments);

    這里的arguments就是$.ajax請求中complete回調的參數。假如,這里沒有找到符合條件的函數,那么,getFunction將會把oncomplete的字符串值作為腳本進行執行,即:getFunction的最后一句:

    return Function.constructor.apply(null, argNames);

    這就是為什么可以直接在OnSuccess中寫JavaScript腳本的原因哦。


    PS:

    OK,主體框架分析完成了,來分析一些其他的東西,主要是Ajax輔助方法里面的AjaxOptions設置問題。

    1) 上面的例子主要以Form來分析,對于Link來說,以上所有的分析都成立,只是<form>變成了<a>,這也是他們的唯一區別,所有的原理是一樣的,也就是監聽所有具有data-ajax的<a>標簽的click事件,然后發起ajax請求,這部分的代碼和前面的代碼段一作用是一樣的,只是后者用于<form>而已,相應的代碼段一就變成了下面這個樣子:

    [javascript] view plaincopy
  • $("a[data-ajax=true]").live("click",?function?(evt)?{??
  • ????evt.preventDefault();??
  • ????asyncRequest(this,?{??
  • ????????url:?this.href,??
  • ????????type:?"GET",??
  • ????????data:?[]??
  • ????});??
  • });??

  • 2) AjaxOptions設置問題

    》Url:默認為form的action,上面提到的jquery.unobtrusive-ajax.js兩段代碼中對其進行了設置,如果有設置data-ajax-url屬性,則取data-ajax-url屬性作為ajax請求的url,否則取<form>action屬性(如果是鏈接的話,則取的是<a>href屬性)。

    ?

    》HttpMethod:默認值為GET,這部分的設置和AjaxOptions.Url是相似的,對于Form來說優先級依次為data-ajax-method屬性,form.action"GET",對于Link來說就是"GET"

    》UpdateTargetId:原則上應是需要更新的html元素的id(MVC的Aajx輔助方法會自動在生成的data-ajax-update屬性前面插入字符'#',參看前面Ajax.BeginForm生成的Html代碼),但是細細查看代碼,你會發現此處可為多個html元素,只要第一個不加#,之后的依次加上即可,如UpdateTargetId ="div1,#div2, #div3",可實現多個div同時更新,甚至于后面的可以是任何jQuery支持的css selector。這部分代碼定義在文件jquery.unobtrusive-ajax.js里的函數asyncOnSuccess中:

    [javascript] view plaincopy
  • mode?=?(element.getAttribute("data-ajax-mode")?||?"").toUpperCase();??
  • $(element.getAttribute("data-ajax-update")).each(function?(i,?update)?{??
  • ????var?top;??
  • ??
  • ????switch?(mode)?{??
  • ????case?"BEFORE":??
  • ????????top?=?update.firstChild;??
  • ????????$("<div?/>").html(data).contents().each(function?()?{??
  • ????????????update.insertBefore(this,?top);??
  • ????????});??
  • ????????break;??
  • ????case?"AFTER":??
  • ????????$("<div?/>").html(data).contents().each(function?()?{??
  • ????????????update.appendChild(this);??
  • ????????});??
  • ????????break;??
  • ????default:??
  • ????????$(update).html(data);??
  • ????????break;??
  • ????}??
  • });??
  • 核心是前兩行代碼:mode獲取更新方式,共有三種模式,InsertBefore,InsertAfter,Replace(在枚舉InsertionMode中定義),從上面的代買來看,默認的是Replace模式;再看下面的element.getAttribute("data-ajax-update"),對于上面的例子,獲取到的應該是"#searchResult",如果將上例中的<UpdateTargetId = "searchResult">改成<UpdateTargetId ="searchResult, div.update">,那么被更新的除了# searchResult之外,還有所有具有‘update’這樣的css類的div元素,原因就在那個each()

    》InsertionMode:只有在設置了UpdateTargetId之后才會生效

    》LoadingElementDuration:只有在設置了LoadingElementId之后才會生效


    總結

    以上是生活随笔為你收集整理的Unobtrusive JavaScript介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。