10/10/2018, 10:48
LINQ to Javascript <= Thư viện hot
Mình có phát triển một thư viện javascript, sử dụng để query object, array, list... Bà con nhảy vào chém hộ mình vài phát, trong quá trình phát triển, bà con chém nhẹ tay thôi
Tải phiên bản minify https://sourceforge.net/projects/lin...js.js/download
Tải js datasource trích từ database northwind https://sourceforge.net/projects/lin...nd.js/download, truy xuất bằng cách viết nortwind.Categories (bảng Categories), nortwind.Orders (bảng Orders)...
Một số hàm thông dụng
all(predicate) trả về nếu tất cả item thỏa điều kiện
any(predicate) trả về nếu một item bất kỳ thỏa điều kiện
select(action) nhận về tập hợp object được chọn lọc từ kết quả của hàm action
order(action, desc) nhận về một tập hợp đã được sắp xếp theo field trả về bởi hàm action
where(predicate) lọc tập hợp thỏa điều kiện predicate
array() chuyển tập hợp thành mảng để xử lý
dump() kết xuất nội dung tập hợp thành chuỗi
grid() kết xuất nội dung tập hợp thành html table
upper(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ hoa
lower(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ thường
capitalize(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ thường
...
Chỉ là một số hàm cơ bản, có tới vài chục hàm và những overload tham số hàm khác nhau, mình chưaa tiện document hết
Ghi chú: những tham số đa phần là action và predicate, 2 thứ này đều có thể là function hoặc string, action thường dùng chọn lọc nội dung kết xuất, predicate thường là biểu thức điều kiện return true / false
Những ví dụ cơ bản:
document.write(linq(northwind.Orders).grid()) // in ra danh sách tất cả hóa đơn
Tải phiên bản minify https://sourceforge.net/projects/lin...js.js/download
Tải js datasource trích từ database northwind https://sourceforge.net/projects/lin...nd.js/download, truy xuất bằng cách viết nortwind.Categories (bảng Categories), nortwind.Orders (bảng Orders)...
Một số hàm thông dụng
all(predicate) trả về nếu tất cả item thỏa điều kiện
any(predicate) trả về nếu một item bất kỳ thỏa điều kiện
select(action) nhận về tập hợp object được chọn lọc từ kết quả của hàm action
order(action, desc) nhận về một tập hợp đã được sắp xếp theo field trả về bởi hàm action
where(predicate) lọc tập hợp thỏa điều kiện predicate
array() chuyển tập hợp thành mảng để xử lý
dump() kết xuất nội dung tập hợp thành chuỗi
grid() kết xuất nội dung tập hợp thành html table
upper(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ hoa
lower(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ thường
capitalize(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ thường
...
Chỉ là một số hàm cơ bản, có tới vài chục hàm và những overload tham số hàm khác nhau, mình chưaa tiện document hết
Ghi chú: những tham số đa phần là action và predicate, 2 thứ này đều có thể là function hoặc string, action thường dùng chọn lọc nội dung kết xuất, predicate thường là biểu thức điều kiện return true / false
Những ví dụ cơ bản:
document.write(linq(northwind.Orders).grid()) // in ra danh sách tất cả hóa đơn
Code:
linq(northwind.Products).order(function() { return this.ProductName; }, true); // sắp xếp bảng sản phẩm theo thứ tự giảm dần của ProductName linq(northwind.Products).order('ProductName', true) // tương tự như trên linq([1, 2, 3, 4, 5, 6]).order(true) // sắp xếp giá trị giảm dần (không sử dụng field) linq(northwind.Products).order('[ProductName, UnitsOnOrder]', [true, false]) linq(northwind.Products).order('[ProductName, UnitsOnOrder]') // sắp xếp theo nhiều field linq(northwind.Products).where(function() { return this.CategoryID == 5 }); linq(northwind.Products).where('this.CategoryID'); //lọc theo điều kiện linq(['hello', 'world']).capitalize() // trả về danh sách ("Hello", "World") linq([1, 2, 3, 4]).odd() // trả về danh sách số lẻ (1, 3) linq(["hello", "world"]).contains("d") // trả về danh sách những item có chứa chữ d linq(["hello", "world"]).contains("D", true) // trả về danh sách những item có chứa chữ D và không phân biệt hoa thường linq(["hello", "world"]).starts("h") // trả về danh sách những item có chữ h ở đầu linq(northwind.Products).select(function() { return { name: this.ProductName, category: this.CategoryID }; }); linq(northwind.Products).select('ProductName') linq(northwind.Products).select('[ProductName, CategoryID]') // kết xuất thành những item có kiểu dữ liệu mảng và có 2 phần tử chứa giá trị của ProductName, CategoryID linq(northwind.Products).select('{ProductName, CategoryID}') // kết xuất thành những item có kiểu là object có thuộc tính ProductName và CategoryID chứa giá trị của những field ProductName và CategoryID linq([1, 2, 3, 4]).count() // đếm số item linq([1, 2, 3, 4]).count('this % 2 == 0') // đếm số item là số chẵn linq(3) tạo tập hợp số từ 0 đến 3 (0, 1, 2, 3) linq(1, 5) tạo một tập hợp số từ 1 đến 5 (1, 2, 3, 4, 5) linq("Hello world") tạo danh sách ký tự từ chuỗi ("H", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d") linq([1, 2, 3, 4, 5]).each(function(key) { alert(this); }); // duyệt tập hợp Khi lọc, select, order, group... hệ thống thực sự chưa query, chỉ đến khi kết xuất bằng những hàm array, get, each... thì nội dung query mới được thực thi. Tốc độ xử lý cũng không đến nỗi tệ, sort bảng Orders có ~800 mất 2-3 ms Những hàm take, first, last, limit(chế thêm cho giống mysql limit), skip, group, join, min, max, sum, avg, concat, union, get(lấy item ở vị trí thứ i)
Bài liên quan
dùng dotnet thì nó có thư viện js khá lớn hỗ trợ cho dataobject và kết nối không đồng bộ với sevice. (datagrid,datagridview,datalist...)
mình cũng đề nghị thay cái
oh, quên mất không biết ý nghĩa của linq là gì. lâu lâu không nhòm là quên sạch
And thank
ví dụ nếu ko viết thêm prototype cho array thì khi
for(var i in myArray) nó chỉ duyệt qua những index của array
Khi có thêm prototype thì nó duyệt qua cả những method mới add vào thành ra phải thêm công đoạn kiểm tra đây có phải là method nội tại của array hay không rồi mới xử lý .v.v.
việc sử dụng linq(values).where().where().order().order().group ().group().first()
là hợp lệ, không phân biệt thứ tự trước sau của mệnh đề
Duy chỉ có những mệnh đề kết xuất first, last, array (những mệnh đề này không kết xuất thành kiểu liệt kê) nên sẽ không gọi nối tiếp những mệnh đề kia được.
Bạn nào muốn viết prototype cho array để dễ sử dụng thì có thể theo mẫu sau:
Object.prototype.linq = function() { return linq(this); };
Sử dụng: [1, 2, 3, 4].linq().odd();
Còn LINQ 2 javascript là cách gọi chung của những dạng xử lý của LINQ, ví dụ LINQ to Object, xử lý những đối tượng trong bộ nhớ chứ chả có kết nối CSDL chi cả, hoặc LINQ to XML, LINQ to File, LINQ to Web .v.v.
[=========> Bổ sung bài viết <=========]
Mình có so sánh một số thư viện LINQ cho javascript khác, sau đây mình chỉ nêu những tính năng nổi bật (các bác đừng cho là mình tự sướng), còn những tính năng không nổi bật thì mời bà con xông vào chém xối xả.
1. Cú pháp đơn giản và hỗ trợ string expression
linq([1, 2, 3]).where(function() { return true });
hoặc linq([1, 3, 4]).where('this % 2 == 0');
So với một số library khác chỉ sử dụng function() {} cho query
http://blog.foxxtrot.net/2010/06/lin...avascript.html
http://linqjs.codeplex.com/ phải thêm dấu $
2. Xử lý trên nhiều loại tập hợp, object list, value list, range, string, regex matches
linq('hello world') // chuỗi
linq(/\d+/, '12213123 213123 21312312') // regex matches
linq([1, 2, 3, 4]) // value list
linq([ {name: 'abc', age: 10}, {name: 'def', age: 11} ]) // object list
linq($('*')).where('this.tagName == "B"') // jquery
So với những thư viện khác chỉ xử lý độc nhất array hoặc object list không xử lý được value list vì những thư viện đó khi where phải cần field name:
http://www.hugoware.net/Projects/jLinq
3. Sắp xếp records trên nhiều fields, một số thư viện chỉ sắp xếp trên 1 field
4. Hỗ trợ tập lệnh query phong phú, sao chép gần đủ của .net, số lượng hàm query chỉ kém thư viện http://linqjs.codeplex.com/
5. Hỗ trợ xử lý trễ
var results = linq(northwind.Orders).where('this.OrderID != null'); // chưa xử lý lệnh where hoặc bất kỳ mệnh đề nào nối tiếp
var array = results.array(); // bắt đầu xử lý để kết xuất thành array
So với một số thư viện xử lý dựa trên cơ sở array thì ở mỗi mệnh đã được chuyển hóa thành array và xử lý ngay tại bước đó =>xử lý ngay khi khởi tạo dù không chắc query đã được sử dụng đến.
6. Hỗ trợ viết những extension cho query
LINQ.Enumerable.extensions.myselect = function(action)
{
return something;
};
linq([1, 2, 3, 4, 5]).myselect();
Một số ví dụ khác:
nói chung bạn giữ quan điểm của bạn thì tùy. xong cũng nên nghĩ người sử dụng sẽ như thế nào.
lấy ví dụ jquery. chẳng ai viết là jquery("elementId").value="123"; chỉ cần thêm thư viện của jquery zô project là bạn có thể tận hưởng
theo tôi chì cách viết của bạn không chuyên nghiệp "bạn kia nói là không dynamic có lẽ cũng là ý này".
bạn có hỏi người dùng sẽ thích viết
linq([1, 2, 3, 4, 5, 6]).order hơn hay viết [1, 2, 3, 4, 5, 6].order hơn
một tiện ích mà mình nghĩ rất hay của linq là sử dụng kí pháp lambda
.select('u=>u.Title')
sẽ hay hơn là .select('this.Title'); sẽ rất hay nhầm lẫn với từ khóa this.
ví dụ
linq([1, 3, 4]).where('this % 2 == 0');
linq($('*')).where('this.tagName == "B"') // jquery
cùng là this nhưng ở 2 câu là khác nhau.
Những cách nói linq2javascript đã có rất nhiều trên mạng, bạn có thể tham khảo, ở đây mình chỉ gọi cho dễ hiểu thôi.
Như mình đã trình bày, không phải mình không muốn viết cho nó ngắn gọn.
Nếu lý giải như bạn thì $('a').attr('href') thì tốt hơn hết jquery nên viết là 'a'.attr('href') cho nó tiện
còn việc bạn develop lại, sử dụng prototype hay ký hiệu $ cho nó ngắn gọn thì đó là quyền mỗi người, để làm chuyện này ko quá khó:
$ = linq;
$([1, 2, 3, 4, 5, 6]).order(); // trông như jQuery nhỉ
hay
Array.prototype.order = function() { return linq(this).order(); }
[1, 2, 3, 4, 5].order();
[=========> Bổ sung bài viết <=========]
Cập nhật bản mới https://sourceforge.net/projects/lin...28.js/download
Có thêm tính năng cài đặt vào các prototype có sẵn để dễ dàng sử dụng, mình cố gắng không cài đặt sẵn vào những prototyp do lo ngại bị xung đột khi sử dụng chung với những hàm tiện ích Moo hay Prototype framework. Do đó nếu bà con nào cảm thấy bất tiện trong code kiếc thì có thể dùng
LINQ.install(<overwrite>, <prototype hoặc class hoặc func>);
<overwrite> chỉ định rằng nếu là true sẽ ghi đè những hàm tiện ích của linq lên những hàm có sẵn của prototype đó nếu bị trùng tên, ngược lại false sẽ chỉ cài đặt những hàm của linq nếu prototype đó chưa có (nên dùng false để tránh xung đột)
Ví dụ: