網頁

2011年11月27日 星期日

前端處理JSON資料與陣列 - 使用 LINQ to JavaScript (1)


在上一篇「前端處理JSON資料 - 轉為陣列以及簡單篩選」說明了如何使用 $.grep() 方法在前端程式中去篩選陣列中的資料,

但是如果要處理的篩選條件是比較複雜時,使用 $.grep() 依然是可行,但總會任人覺得不是那麼方便,

尤其是寫 C# 的開發者在 .NET Framework 3.5 之後對於集合資料的操作已經熟悉並且習慣了 LINQ 語法,

而在前端程式中卻沒有這樣方便的處理方式,在處理集合資料時就會覺得綁手綁腳的,

其實這情形早已經有人做了一個解決方案,「LINQ to JavaScript」( 簡稱為 JSLINQ ),

在2009年的時候在MSDN學習園地的CodePlex教學中就有對這個函式庫做介紹「LINQ to JavaScript: 在 JavsScript 也可以用 LINQ

接下來就來說明一下使用的方式。


LINQ to JavaScript (JSLINQ)

網址:http://jslinq.codeplex.com/

下載:http://jslinq.codeplex.com/releases/view/28886

目前的版本是 v2.10 , 2009年6月16日發佈

 

下載「JSLINQ_v2.10_SourcePlusExamples.zip」檔案並解壓縮,

image

如果想要馬上了解JSLINQ有什麼樣的功能以及可以做到什麼樣的操作,可以馬上看「Samples.htm

image

針對JSLINQ裡面每一種方法的操作做詳盡的說明,而JSLINQ也有提供完整的Sample Unit Tests「TestSamples.htm

image

而最重要的就是JSLINQ的函式庫本身,在「scripts」目錄中有三個檔案:JSLINQ.js, JSLINQ-vsdoc.js, Samples.js

image

其中Samples.js就是Sample的前端程式,包含了範例資料以及執行程式本身還有單元測試的程式,

我覺得這個Samples.js相當重要,因為裡面有相當詳盡的程式操作方法,甚至是前端程式的單元測試寫法可以作為參考,

如果說當使用JSLINQ遇到問題時,可以開啟 Samples.js 來查閱程式內容,就應該可以略知一二。

 

而「JSLINQ.js」就是函式庫本身,這是最重要的檔案,而使用上只要將檔案加入到專案並且include之後就可以使用,

「JSLINQ-vsdoc.js」這個檔案對於使用Visual Studio進行開發的程式人員也是相當重要,

因為只要在在網頁中或是檔案中參照這個檔案,在Visual Studio裡面出現智能顯示 ,

 

ASP.NET MVC 3 Razor ViewPage中加入 vsdoc的方式

image

獨立的JS檔案中加入 vsdoc 的方式

image

這邊提供一個簡單的方式在獨立JS檔案快速加入reference的方法,

首先在方案總管中選定你要加入參考的JS檔案

image

選定之後,按住滑鼠的左鍵不放,並且直接拖曳到已開啟的JS檔案裡,然後放開,就會自動加入一段reference的語法

image

image

PS.

記得在加入參考之後一定要更新 JScript Intellisense,更新的快捷鍵是「CTRL + SHIFT + J」如此才能正確顯示Intellisense。

image

 

如何使用並顯示JSLINQ的Intellisense

這地方要特別說明一下,不然很多人一定會發生跟我一樣的狀況,就是語法使用都正確,但怎麼試就是無法顯示Intellisense,

原本JSLINQ的操作方式

image

假如要接著繼續使用JSLINQ的方法,卻無法顯示Intellisense…

image

 

而在Readme.txt文件檔案中也說到,除了原本建立instance的方法:

var option1 = JSLINQ(myArray);

也另外提供了另一組建立instance的方法:

var option2 = new JSLINQ(myArray);

 

所以我們就用另外的建立instance的方式,

image

並且接著看看會不會顯示JSLINQ的Intellisense…

image

Done!可以正常顯示JSLINQ的Intellesense啦!這樣就方便我們編寫使用JSLINQ的前端程式了…

 

JSLINQ有哪些方法

我們在Visual Studio中透過Javascript Parser來看看JSLINQ有提供哪些方法,

image

JSLINQ提供了19個方法(從Where開始一直到最後的LastOrDefault),這些基本的方法就如同在.NET中使用LINQ是一樣的。

 

使用 JSLINQ

接下來我們直接使用JSLINQ Sample中的測試資料來做個簡單操作,

image

 

情境一:我們要取出FirstName是「Chris」的資料
$(document).ready(function ()
{
    var result = "";
 
    var test = new JSLINQ(Samples.People)
        .Where(function (item) { return item.FirstName == "Chris"; })
        .Select(function (item) { result += item.ID + "|" + item.FirstName + " " + item.LastName + "<br/>"; });
 
    $('#ResultContent').html(result);
 
});

執行結果:

image

 

情境二:取出FirstName中有包含「s」或「S」的資料(記住!大小有區分喔)
$(document).ready(function ()
{
    var result = "";
 
    var test = new JSLINQ(Samples.People)
        .Where(function (item)
        {
            return item.FirstName.indexOf("S") >= 0 || item.FirstName.indexOf("s") >= 0
        })
        .Select(function (item) { result += item.ID + "|" + item.FirstName + " " + item.LastName + "<br/>"; });
 
    $('#ResultContent').html(result);
 
});

執行結果:

image

 

情境三:取出BookIDs中含有「1001」的資料(這個就比較進階,集合中再去對資料內的集合進行篩選)
$(document).ready(function ()
{
    var result = "";
 
    var test = new JSLINQ(Samples.People)
        .Where(function (item)
        {
            return new JSLINQ(item.BookIDs).Count(function (inner) { return inner == 1001 }) > 0
        })
        .Select(function (item) { result += item.ID + "|" + item.FirstName + " " + item.LastName + "|" + item.BookIDs + "<br/>"; });
 
    $('#ResultContent').html(result);
 
});

執行結果:

image

 

基本的情境說明就到此為止,如果要詳加了解JSLINQ各個方法的操作可以仔細研究 Sample.htm 以及 Sample.js並且多做練習,相信就會對JSLINQ輕鬆上手。

 

JSON資料轉陣列後使用JSLINQ進行操作

延續上一篇「前端處理JSON資料 - 轉為陣列以及簡單篩選」的資料來做演練,使用JSLINQ來做資料的篩選

原始取得的資料:

image

假定我們要取得CategoryID是「1」的Product出來,使用JSLINQ的寫法如下:

function UseJSLinq()
{
    var result = GetData(ActionUrls.GetProducts);
 
    var details = "<hr/>";
 
    var currentData = JSLINQ(result)
        .Where(function(item) { return item.CategoryID == "1"; })
        .Select(function(item)
        { 
            details += item.ProductID + "|" + item.ProductName + "|"  + item.CategoryID + "|" + item.CategoryName + "|"+ item.SupplierID + "|"+ item.CompanyName + "|" + "<br/>"; 
        });
 
    $('#Products').html(details);
}

執行的結果:

image

 

在上面的各個範例當中,我們都是最後在Select()或是Count()當中的方法進行資料的最終處理,

但如果說我們使用JSLINQ篩選後的資料還不需要馬上做最後處理(如顯示的處理),或許還要對篩選的資料再進行加工,

此時我們可以用以下的方法來操作:

function UseJSLinq2()
{
    var result = GetData(ActionUrls.GetProducts);
 
    var currentData = JSLINQ(result)
        .Where(function(item) { return item.CategoryID == "1"; })
        .Select(function(item){ return item;});
 
    var details = currentData.items.length + "<hr/>";
 
    $.each(currentData.items, function(index, item)
    {
        details += item.ProductID + "|" + item.ProductName + "|"  + item.CategoryID + "|" + item.CategoryName + "|"+ item.SupplierID + "|"+ item.CompanyName + "|" + "<br/>";  
    });
 
    $('#Products').html(details);
}

執行的結果:

image

一定有人覺得這兩個方法除了說多了一個Count資料外,還有什麼地方式不同的嗎?

第一個方法:

var currentData = JSLINQ(result)
  .Where(function(item) { return item.CategoryID == "1"; })
  .Select(function(item)
  { 
    details += item.ProductID + "|" + item.ProductName + "|"  + item.CategoryID + "|" + item.CategoryName + "|"+ item.SupplierID + "|"+ item.CompanyName + "|" + "<br/>"; 
  });

第二個方法:

var currentData = JSLINQ(result)
  .Where(function(item) { return item.CategoryID == "1"; })
  .Select(function(item){ return item;});

 

第一個方法是直接在JSLINQ的Select()方法中把要顯示的資料給處理好,第二個方法則只是單純的將資料給返回,

但是第二個方法對於經過JSLINQ處理後返回的資料處理是有個地方需要特別提醒,

那就是不能直接對返回的資料做處理,像第二個方法所返回的資料是放在 currentData 中,

如果是直接對 currentData 做處理的話,就會有以下的結果:

image

用Firebug進行中斷偵錯來了解一下 currentData 裡面的情況,

image

這麼看就很清楚了,因為經由JSLINQ處理後所返回的資料集合,會放在 items 中,所以無法直接對 currentDate 做處理,

而是需要對 currentData.items 做處理。

所以再看一次第二個方法:

function UseJSLinq2()
{
    var result = GetData(ActionUrls.GetProducts);
 
    var currentData = JSLINQ(result)
        .Where(function(item) { return item.CategoryID == "1"; })
        .Select(function(item){ return item;});
 
    var details = currentData.items.length + "<hr/>";
 
    $.each(currentData.items, function(index, item)
    {
        details += item.ProductID + "|" + item.ProductName + "|"  + item.CategoryID + "|" + item.CategoryName + "|"+ item.SupplierID + "|"+ item.CompanyName + "|" + "<br/>";  
    });
 
    $('#Products').html(details);
}

針對 currentData.items 做處理,而不是對 currentData 本身,要特別注意這個小地方的不同。

 

補遺:使用ToArray()方法

發佈文章後再一次Review文章內容,然後發現到JSLINQ有提供一個方法:ToArray()

看來這應該是把JSLINQ處理後的資料中items的部份給提出,看看原始碼的內容:

image

果不其然……這就是我沒有仔細看原始碼的後果,天真的以為JSLINQ忘記要做這個步驟,

所以我們就可以使用ToArray()方法將JSLINQ處理後的items給取出來使用,

那前面的那一段程式碼就可以改成下面的內容:

function UseJSLinq3()
{
  var result = GetData(ActionUrls.GetProducts);
  var currentData = new JSLINQ(result)
    .Where(function(item) { return item.CategoryID == "1"; })
    .Select(function(item){ return item;})
    .ToArray();
  var details = currentData.length + "<hr/>";
  $.each(currentData, function(index, item)
  {
    details += item.ProductID + "|" + item.ProductName + "|"  + item.CategoryID + "|" + item.CategoryName + "|"+ item.SupplierID + "|"+ item.CompanyName + "|" + "<br/>";  
  });
  $('#Products').html(details);
}

而最後的執行結果就如直接拿currentData.items的執行結果是相同的:

image

補上並且更正原本文章內容的缺漏與錯誤。

 

以上就是對LINQ to JavaScript(JSLINQ)的一些簡單的說明以及操作示範,

透過JSLINQ的操作讓我們可以在開發前程式的時候繼續使用LINQ相同觀念的方式來操作集合資料。

 

參考連結:

CodePlex – LINQ to JavaScript

MSDN CodePlex教學 - LINQ to JavaScript: 在 JavsScript 也可以用 LINQ

 

以上

2 則留言:

  1. 另一款類似的LinqJs最後更新日期比較新
    http://linqjs.codeplex.com

    回覆刪除
  2. 有關Linq.js也會在之後介紹,
    目前的前端語言使用類似Linq語法操作,好像SQLike與linq.js這兩種比較完整

    回覆刪除