前端開發中JavaScript代碼的維護總是讓人頭疼,特別是在富客戶端應用中,必須要編寫非常龐大的JavaScript代碼,雖然JavaScript聲稱是面向對象的語言,但對於現代語言中常見的繼承、強類型等的支持十分有限。如果我們能夠將C#語言中的特性運用於JavaScript上,那么肯定將極大地提高JavaScript代碼的維護性,提升開發效率。Saltarelle編譯器就是這樣的一個工具,他能將C#代碼編譯為JavaScript代碼。
本文將展示如何使用Saltarelle編寫JavaScript代碼,我們將結合Saltarelle.jQuery和Saltarelle.Knockout庫說明如何使用Saltarelle。本文使用Visual Studio 2012作為開發工具,通過NuGet獲取相關擴展包。
1、首先新建一個空ASP.NET應用項目,此項目作為前端演示網站,項目名稱為Web
2、添加一個類庫項目,作為JavaScript腳本項目,該項目使用Saltarelle編譯器自動生成腳本代碼,項目名稱為Scripts
3、選擇Scripts項目,單擊右鍵,選擇“管理NuGet程序包”,在程序包管理界面,在上方搜索窗口中輸入Saltarelle,搜索有關Saltarelle的包:
依次安裝Saltarelle C# to JavaScript Compiler、Runtime library for the Saltarelle C# to JavaScript… 、Metadata required to use jQuery with Saltarelle …、Metadata required to use Knockout with Saltarelle …
4、Saltarelle包會更新Scripts項目,添加必要程序集引用,並修改項目使用Saltarelle編譯器,由於Visual Studio 本身Bug,我們需要手動卸載並重新載入Scripts項目。此操作通過項目右鍵菜單完成。
5、修改Scripts項目類型:單擊Scripts項目,右鍵選擇屬性,在輸出類型中選擇“控制台應用程序”,做此項修改的原因是讓Saltarelle編譯器自動調用Scripts的入口方法(即,Program的Main方法)
6、打開Properties文件夾下的AssemblyInfo.cs代碼文件,注釋掉一下ComVisible和Guid特性:
// 將 ComVisible 設置為 false 使此程序集中的類型 // 對 COM 組件不可見。如果需要從 COM 訪問此程序集中的類型, // 則將該類型上的 ComVisible 特性設置為 true。 //[assembly: ComVisible(false)] // 如果此項目向 COM 公開,則下列 GUID 用於類型庫的 ID //[assembly: Guid("ecc66b86-53da-44b6-b83a-87b52da11e91")]
7、將Scripts項目中自動添加的Class1.cs代碼文件修改為Program,並添加Main方法:
namespace Scripts { class Program { static void Main() { } } }
8、生成Scripts項目,完成后,我們可以在生成輸出目錄看到所生成的Scripts.js文件
接下來,我們演示如何使用jQuery:
jQuery中可以使用ready注冊在頁面載入完成后所要執行的程序,在Saltarelle.jQuery中,我們可通過OnDocumentReady方法來完成相同的功能,下面示例實現在頁面載入完成后彈出提示框的功能:
1、在Program.cs中添加System.Html和jQueryApi命名空間
2、修改Main方法,代碼如下:
using System.Html; using jQueryApi; namespace Scripts { class Program { static void Main() { jQuery.OnDocumentReady(() => { Window.Alert("Page is loaded"); }); } } }
copy $(TargetDir)$(TargetName).js $(SolutionDir)Web\Scripts\$(TargetName).js
5、為了保證在生成Web項目時能自動更新Scripts.js腳本,可在Web項目中添加對Scripts項目的引用
6、下面在Web項目中添加一個名稱為Index.html的HTML頁面。在head標簽內添加必要js文件的引用:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script type="text/javascript" src="Scripts/mscorlib.min.js"></script> <script type="text/javascript" src="Scripts/jquery-1.9.1.js"></script> <script type="text/javascript" src="Scripts/Scripts.js"></script> </head> <body> </body> </html>
using System; using KnockoutApi; namespace Scripts { public class IndexViewModel { // 頁面標題, 使用Observable表示該字段支持更改通知,當值改變時,它所關聯的UI將自動更新 public Observable<string> PageTitle = Knockout.Observable<string>(); // 表示支持更改通知的數組 public ObservableArray<LogItem> Logs = Knockout.ObservableArray<LogItem>(); } public class LogItem { public string Level = String.Empty; public DateTime Time; public String Message = String.Empty; } }
注意:有關如何使用Knockout實現MVVM模式,請參考Knockout官方網站
2、在Main方法中綁定ViewModel:
using System.Html; using jQueryApi; using KnockoutApi; namespace Scripts { class Program { static void Main() { jQuery.OnDocumentReady(() => { Window.Alert("Page is loaded"); IndexViewModel vm = new IndexViewModel(); vm.PageTitle.Value = "未命名"; Knockout.ApplyBindings(vm); }); } } }
3、將包中Knockout庫文件拷貝到Web項目的Scripts目錄中
4、在Index.html文件中添加對Knockout庫js文件的引用
<script type="text/javascript" src="Scripts/mscorlib.min.js"></script> <script type="text/javascript" src="Scripts/jquery-1.9.1.js"></script> <script type="text/javascript" src="Scripts/knockout-2.2.0.min.js"></script> <script type="text/javascript" src="Scripts/Scripts.js"></script>
5、在Index.html使用ViewModel,實現數據綁定
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script type="text/javascript" src="Scripts/mscorlib.min.js"></script> <script type="text/javascript" src="Scripts/jquery-1.9.1.js"></script> <script type="text/javascript" src="Scripts/knockout-2.2.0.min.js"></script> <script type="text/javascript" src="Scripts/Scripts.js"></script> </head> <body> <h1 data-bind="text:pageTitle"></h1> <button id="btnEdit">修改標題</button> <p> <strong>日志:</strong> </p> <ul data-bind="foreach:logs"> <li>[<span data-bind="text:time"></span>]<span data-bind="text:level"></span><br /><span data-bind="text:message"></span></li> </ul> </body> </html>
需要注意的是,Salarelle編譯器在生成js文件時,會自動對C#中的名稱轉換為js規范,故我們看到在html中,數據綁定時所使用的字段名稱都是以小寫字母開始。
6、在Html中有個“修改標題”的按鈕,我們需要為此按鈕增加事件處理函數,這里我們采用jQuery的click事件綁定方式,只需在Main方法、OnDocumentReady中增加以下代碼:
jQuery.Select("#btnEdit").Click((s) => { vm.PageTitle.Value = "標題" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); vm.Logs.Value = vm.Logs.Value.Concat(new LogItem() { Level = "信息", Time= DateTime.Now, Message = "修改了標題" }); });
代碼很簡單,直接修改PageTitle,並向日志列表中添加一項日志。
7、啟動調試,單擊頁面中按鈕,執行效果