前端開發中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"); }); } }}
接下來,我們如何在Web項目中使用產生的js檔案呢?其實使用Scripts所產生的js代碼與其他js代碼是完全一樣的,但在引用編譯後的js檔案之前,我們需要引用Saltarelle運行時js。該js可在Salarelle.Runtime包目錄中找到:
1、在Web項目中建立一個名稱為Scripts的目錄,該目錄用於儲存項目中的js檔案
2、開啟解決方案所在檔案夾,將 packages\Saltarelle.Runtime.2.2.0下的mscorlib.js或mscorlib.min.js(壓縮版)拷貝到Web項目的Scripts目錄。
3、當然,由於我們使用了jQuery,所以也必須將jQuery庫檔案拷貝到Scripts目錄下,在packages\Saltarelle.jQuery.1.9.0目錄下也存在jQuery js檔案
4、為了保證Scripts下的Scripts.js總是最新的,我們可以在Scripts項目的產生後事件中加複製命令將Scripts.js複製到Web項目的Scripts目錄下:在Scripts項目屬性中,選擇建置事件,在後期建置事件中輸入一下命令:
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>
7、啟動調試,開啟頁面後將彈出“Page is loaded”的提示。
Knockout是一個在js中實現MVVM模式的庫,他能提供類似WPF中資料繫結的功能。
1、首先在Scripts項目中添加一個ViewModel類,代碼如下:
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、啟動調試,單擊頁面中按鈕,執行效果
原始碼下載