[Question] Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
05/04/2008 04:00:19 (+0700) | #1 | 123271 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Đối với nhiều người, việc lập trình javascript (đặc biệt là trong các ứng dụng web 2.0) không lấy gì làm nhẹ nhàng cho lắm. Do đặc thù của interface giữa JS và DOM, viết JS nhiều khi không dài không xong việc. Với mình viết code JS càng dài dòng thì càng khó debug, trong khi debug JS là một việc tương đối mệt nhọc .
Để giảm thiểu gánh nặng trong lập trình JS, lựa chọn một framework tốt để sử dụng là việc làm cần thiết. Một framework tốt sẽ giúp lập trình viên tránh được mối lo xung quanh các vấn đề như: cross browser, lập trình hướng đối tượng, tạo animation,... với JS, làm source code trở nên sáng sủa và ngắn gọn. Mặc dù vậy, nếu chỉ để giải quyết một vài bài toán gọn nhẹ, viết một vài hiệu ứng đơn giản cho ứng dụng web mà phải import cả một framework đồ sộ dài đến tận vài ngàn dòng lệnh (Như Prototype, jQuery, YUI, Dojo,...), thì liệu có đáng không nhỉ? Nếu cũng giống như mình, bạn trả lời cho câu hỏi này là “không”, và bạn sẵn sàng bỏ thời gian để tìm hiểu thêm về lập trình AJAX, xin mời cùng mình dạo qua từng bước quá trình xây dựng DHTiny- một thư viện JS bé nhưng vừa đủ để dùng.
Mục đích của mình khi giới thiệu đến các bạn các bước tạo thư viện này là để chia sẻ một số kỹ năng nho nhỏ về JS, đồng thời rất mong được tiếp thu ý kiến đóng góp từ phía các bạn để nâng cấp nó. Mình sẽ bắt đầu giới thiệu từ phần core trước, phần utility sẽ được bàn đến sau này .
Mời bạn ghé thăm trang Google code của thư viện: http://code.google.com/p/dhtiny/ |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
05/04/2008 04:09:30 (+0700) | #2 | 123275 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Tổng quan về DHTiny
Mình viết cái này vào những ngày nghỉ và trong lúc ở công ty chẳng có gì để làm cả . Vì mình không có nhiều thời gian để viết đều tay, nên nó mới chỉ gồm một core module và một ít module nhỏ phục vụ cho việc tạo widget và animation. Bản core mới nhất của nó mới chỉ dài khoảng dưới 400 dòng, nhưng đã có đủ những tiện ích mong muốn: gói gọn cú pháp JS nói chung, hỗ trợ cross-browser, đơn giản hóa và tường minh hóa vấn đề lập trình hướng đối tượng. Tạm thời việc phòng chống Hijacking hay mã hóa source code mình vẫn chưa có thì giờ thực hiện.
Dưới đây là các vấn đề đặt ra của lập trình JS và cách giải quyết trong DHTiny :
1. Vấn đề: Rút gọn cú pháp JS:
Nếu bạn không sử dụng framework, khi tạo ra một đối tượng trong document body, thiết lập thuộc tính sự kiện hay style cho nó, bạn phải viết khá nhiều dòng lệnh:
Code:
var object = document.createElement(“button”);
object.id = “button1”;
object.innerHTML = “Click me!”;
document.body.appendChild(object);
object.style.color = “red”;
object.style.width = “30px”;
object.style.height= “50px”;
object.style.border = “solid 1px green”;
object.onclick = function() { alert(“You’ve just clicked on a button!”);}
hoặc gọn hơn chút đỉnh khi viết style:
Code:
with(object.style) {
position: “absolute”;
top = “10px”;
left = “10px”;
......
}
Câu hỏi đặt ra là: có cách nào thiết lập ngần ấy thuộc tính một cách ngắn gọn hơn không? Tất nhiên là “CÓ”! DHTiny sẽ giúp bạn viết theo cách như sau:
Code:
// Dòng hơi dài nên mình phải break cho dễ hiển thị trong forum
var object = $ce(“button”,
{id: “button1”, html:”Click me!”, size: [30,50], pos: [10,10]}
).$jump($body);
hoặc viết dài hơn, rõ hơn 1 chút, để bạn thấy đoạn code giống trình tự trên đây và hiểu thêm một chút về cách viết trong DHTiny:
Code:
var object = $ce(“button”, {id:”button”, html: “Click me!” }).$jump($body).$css({bounds:[10,10,30,50], color: “red”});
$id(“button1”).onclick = function () {alert(“Clicked!”);}
Mình đã sử dụng đồng thời vài thao tác nhỏ để rút ngắn cú pháp: a. viết loạt hàm hỗ trợ gọi inline; b. tạo shortcut cho các hàm tên dài; c. thiết lập đối tượng theo loạt thuộc tính cho trước trong 1 collection; d. tạo shortcut cho tên thuộc tính lớp trong; và e. hỗ trợ variation cho mọi hàm có trong thư viện.
a. Tạo shortcut cho các hàm có tên dài:
Các hàm JS hỗ trợ làm việc với DOM có cú pháp khá dài, do đó ta cần tạo loạt các hàm “shortcut” để viết cho nhanh và đỡ bị nhầm lẫn. Vì trên đây chỉ là cách viết ưa thích của mình, nên ai đó có thể không vừa ý với kiểu ký hiệu $[tên hàm viết tắt]. Bạn có thể lựa chọn các tên viết tắt như ý để thay thế cho những chuỗi loằng ngoằng đáng ghét: document.createElement() hay document.getElementById(), object.style.width=..., v.v... Ví dụ như khi viết lại hàm lấy đối tượng theo ID, mình đã dùng $id:
Code:
function $id(_id) { return document.getElementById(_id); }
// Đây chỉ là ví dụ, ko phải hàm $id() trong DHTiny
Với hàm tạo một element trong DOM mình chọn $ce:
Code:
function $ce(tag) { return document.createElement(tag)};
// Đây chỉ là ví dụ, ko phải hàm $ce() trong DHTiny
Hoặc khi thiết lập style, mình đã viết hàm $css:
Code:
function $css(object, {loạt thuộc tính}){....};
b. Viết loạt hàm hỗ trợ gọi inline:
Nguyên tắc để viết được các dòng lệnh inline là rất giản dị và chắc nhiều bạn đã quá rõ: luôn return con trỏ đến đối tượng sau khi kết thúc hàm. Ví dụ như: sau khi viết các hàm:
Code:
function setId(_id) {
this.id = _id;
return this; // đây là cái cớ để gọi inline
}
function setSize(_width, _height) {
this.style.width = _width + “px”;
this.style.height = _height + “px”;
return this; // đây là cái cớ để gọi inline
}
function setPos() {}; // Cùng dạng như setSize
function setOpacity() {}; // Cùng dạng như setSize
...và gắn chúng vào đối tượng/lớp đối tượng/class, ví dụ theo kiểu “thô bạo” như thế này:
Code:
object.setId = setId;
object.setSize = setSize;
object.setPos = setPos;
object.setOpacity = setOpacity;
Từ đấy trở đi bạn có thể gọi chúng inline như sau:
Code:
object.setId(“button1”).setSize(30,50).setPos(3,4).setOpacity(40).onclick=function() {}
Trên đây chỉ là ví dụ. Trên thực tế trong DHTiny việc gán “thô bạo” như trên không vất vả đến thế .
c. Viết một hàm hạt nhân dùng để thiết lập loạt thuộc tính cho đối tượng:
Mình gọi đây là hàm hạt nhân, vì đây chính là xử lý căn bản nhất giúp mình thực hiện mọi việc một cách cực kỳ nhanh chóng. Kể từ các thao tác viết gọn code JS thông thường, đến định nghĩa nhanh đối tượng, mở rộng class, thậm chí là cả việc mã hóa source code của thư viện sau này, mình đều phải tựa vào nó.
Về cơ bản, nó thực chất là một hàm Deep Copy (Clone) đối tượng trong javascript, được viết theo kiểu như sau:
Code:
function $null(obj) { // Kiểm tra đối tượng có rỗng ko
return (obj == null || obj == undefined);
}
function $set(_obj, _props) {
if ($isNull(_props)) return _obj; // Ko có gì để gán
if (typeof _props != “object”) {
_obj = _props; // Gán giá trị kiểu cơ bản
}
else {
for (var x in _props) { // Duyệt qua từng thuộc tính trong collection
if (!$null(_props[x]))
try {
_obj[x] = $set(_obj[x], _props[p]); // Gọi đệ quy để gán thuộc tính lớp trong
}
catch (_error_) {};
}
}
return _obj; // Phục vụ cho gọi inline sau này
}
Với sự có mặt của hàm $set, bạn có thể gán loạt thuộc tính cho đối tượng như sau (Tạm thời điều kiện để sử dụng nó là bạn phải nắm rõ các thuộc tính có thể gán cho đối tượng trong Javascript):
Code:
$set(obj, {id: “button1”, onclick : function() {alert(“hihi”);}, innerHTML: “hahaha” });
Và bạn có thể dễ dàng nhận ra bản chất của hàm định nghĩa style (hàm $css) mà mình đã viết có dạng:
Code:
function $css(obj, _style) { return $set(obj.style, _style);}
Nó có thể được gọi theo chùm như sau:
Code:
$css(object, {width: “100px”, height:”80%”, backgroundColor:”red”, border: “solid 1px red”});
d. Tạo shortcut cho các thuộc tính hay được sử dụng:
Trên đây mình đã đưa ví dụ về hàm setSize và setPos. Tại sao chúng ta phải viết
Code:
$css(object, {width: “100px”, height:”80%”, top:”80px”, left:”30px”});
... khi đã có $set() trong tay? Dựa vào đặc tính thú vị của ngôn ngữ prototype như JS, ta sẽ tạo một bộ các shortcut cho các hàm kiểu setSize, setPos để hàm $set nhận ra phải làm gì khi gán giá trị cho thuộc tính đã được viết tắt.
Cách viết như sau:
Định nghĩa một bộ shortcut:
Code:
var shortcut = {size: setSize, pos: setPos, bg: setBackground,....} // Trỏ tập hợp shortcut đến các hàm đã viết sẵn
Sau đó viết lại hàm $set cho phù hợp:
Code:
function $set(_obj, _props) {
if ($isNull(_props)) return _obj; // Ko có gì để gán
if (typeof _props != “object”) {
_obj = _props;
}
else {
for (var x in _props) {
if (!$null(_props[x]))
try {
if (shortcut[x]) // Nếu shortcut đã được định nghĩa rồi, ta dùng hàm shortcut
_obj[x] = shortcut[x](_props[p]); // Giá trị cần gán được chuyển vào làm tham số cho hàm shortcut.
else // Gán như bình thường
_obj[x] = $set(_obj[x], _props[p]);
}
catch (_error_) {};
}
}
return _obj; // Phục vụ cho gọi inline sau này
}
Kết quả: trong DHTiny bạn có thể định nghĩa nhanh đối tượng theo cú pháp mình thích:
Code:
$set(object, {bg: “red”, size:[30,40], pos: [50,50]});
Mặt khác, để loạt hàm bạn viết có thể gọi trực tiếp từ một đối tượng được sử dụng nhiều lần, ta có thể “vỗ béo cho đối tượng” một cách nhanh chóng:
Code:
$set(obj, shorcut); // Nhét 1 loạt hàm tiện ích trong tập hợp shortcut vào trong đối tượng.
e. Hỗ trợ variation (overload) cho mọi hàm có trong thư viện:
Giả sử bạn đã tạo được loạt hàm $ce, $id, $css, $set rồi, làm thế nào để gọi inline chúng? Rõ ràng, như đã nói trên đây, ta cần phải sửa lại chúng sao cho cuối hàm có return con trỏ this. Cụ thể thế nào thì mời các bạn xem đoạn code ví dụ dưới đây:
Code:
function $css(obj, _style) {
if (arguments.length <2) // Overload nhờ vào số tham số đầu vào
return $css(this, obj);
else return $set(obj.style, _style);
}
var object.$css = $css; // Đính hàm $css vào object
Giờ ta có thể thoải mái gọi hàm $css theo 2 cách:
Code:
$css(obj, {bg: “red”, size:[30,40], pos: [50,50]});
Hoặc: Code:
obj.$css({bg: “red”, size:[30,40], pos: [50,50]});
Với những gì giới thiệu ở trên, bạn có thể hiểu được cách làm của mình nhằm rút ngắn cú pháp JS. Chi tiết việc tổ chức hàm thế nào để thư viện DHTiny có thể được gọi một cách nhanh chóng và hiệu quả, đồng thời bổ sung các tính năng nâng cao khác ra sao, mời các bạn xem và góp ý trong bài viết sau của mình.
|
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
05/04/2008 06:19:19 (+0700) | #3 | 123300 |
|
learn2hack
Elite Member
|
0 |
|
|
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
|
|
Bộ thư viện của bạn rất tuyệt và rất hữu ích, xem cách bạn làm mình cũng học hỏi được nhiều.
Mình có chút góp ý thế này: xem phần bạn viết ở trên mình thấy bạn tập trung vào việc edit đối tượng (bao gồm gán, copy, hay sửa đổi, ...), ngoài ra bạn cũng đã có 1 vài code về shortcut và code inline giúp cho việc viết code ngắn gọn hơn. Nhưng mình thấy còn 1 vấn đề về selector thư viện của bạn chưa tập trung đến. Trong 2 bộ thư viện jQuery và prototype mà mình có dịp làm quen thì phần này là phần mở đầu và tối quan trọng của họ. Sở dĩ như vậy vì nó giúp bạn tìm kiếm, chọn lọc các đối tượng cực kì nhanh và dễ dàng, chọn lọc xong rồi mới nói chuyện thao tác với chúng. Thông thường họ hỗ trợ selector theo CSS luôn để dễ hiểu. Nếu như DHTiny bổ xung kĩ lưỡng chỗ này thì rất ổn. |
|
Blog: http://hontap.blogspot.com
Tải phần mềm miễn phí: http://www.taiphanmem.org |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
05/04/2008 07:23:37 (+0700) | #4 | 123307 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Cảm ơn bạn đã góp ý. Mặc dù mình cái bạn nhắc mình định để ở bài viết sau, nhưng tạm thời mình xin được trả lời như sau:
Tuy cú pháp không thể ngắn tối đa như jQuery (Đúng ra là viết theo cách của jQuery nhìn cái ko dễ gì hiểu ngay nên mình không theo), nhưng DHTiny đã có hỗ trợ một vài hàm shortcut dễ nhớ giúp chọn lọc và làm việc với đối tượng/tập đối tượng như sau:
- Hàm có quy mô nhỏ nhất là $id(param): Nhận tham số đầu vào là 1 object hoặc ID của object, return một đối tượng có đủ tính năng của thư viện. Ví dụ, ta có thể tạo ra 1 đối tượng DIV bị làm mờ trong document body, rồi gọi nó ra làm việc như sau:
Code:
// Một trong số các cách viết để tạo đối tượng DIV
var d = $ce("div", {id: "myDiv", bg:"blue", bounds: [10,10,100,100], opac: 40}).$jump($body);
// Gọi ra để thiết lập thêm vài thuộc tính
$id("myDiv").$css({className: "myClass", color:"red"}).$set({onmousedown: function() { alert("hihi")}});
// Cho nó khả năng drag & drop, khi drag thì nó được đặt độ sáng 100% và chuyển màu
$id("myDiv").$setDrag({opac: 100, bg: "purple"});
// Có thể viết $id(d) nên tham số của hàm là string hay object thì ko cần nhớ rõ cũng được
- Hàm $tag(tagName, container) gom tập đối tượng nằm trong container theo tag. Tạm hiểu nó gần giống như document.getelementByTagName(), nhưng có bổ sung thêm context giúp định vị được vị trí làm việc.
- Hàm $class() giúp chọn lọc đối tượng theo className. Ở đây className không đơn giản chỉ là liên quan đến CSS, mà nó cũng chính là cái mình chọn để quản lý tất cả các instance của một class (Tất nhiên phải là các instance và class được tạo ra theo cách của DHTiny thì mới gọi nhanh các hàm trong thư viện được).
- Các tập $instances["className"] lưu trữ mọi instance của các class được tạo ra bởi DHTiny (Sau này mời bạn xem và góp ý cho phần lập trình hướng đối tượng của DHTiny)
- Ngoài ra, còn một số hàm khác nho nhỏ nữa giúp thay đổi đồng loạt thuộc tính của một tập đối tương cùng nhóm (Chủ yếu là cùng className, hoặc cùng trỏ đến một hàm xử lý)
Mình có khuyết điểm là mới đọc qua source của Prototype hay jQuery thôi, chưa dùng thử để học hỏi thêm. Có lẽ dùng nhiều sẽ nghĩ ra được khối cái mới. Rất mong được tiếp tục nhận được sự đóng góp của tất cả các bạn! |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
05/04/2008 11:33:48 (+0700) | #5 | 123336 |
|
learn2hack
Elite Member
|
0 |
|
|
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
|
|
Mình góp ý chỗ selector đó vì chỗ đó giúp chúng ta làm việc cực nhanh trên JS. Nếu như bạn chỉ đơn thuận tạo các shortcut và không có 1 cú pháp nổi bật để chọn lọc các phần tử, mà chỉ đơn thuần dựa trên các hàm có sẵn thì e là khó có thể sánh được với các bộ thư viện khác. VD đơn giản với jQuery có thể chọn phức tạp tới mức như:
Code:
$('#list > li p:last > a:first').each(function() {});
Còn prototype thì đây gần như là toàn bộ cơ sở cho phần core của họ, các phần sau chỉ là các module thôi.
Nhưng mà bạn đang định giới thiệu chức năng selector ở bài tiếp theo nên chúng ta sẽ thảo luận thêm về nó khi bạn post xong đã .
Còn khuyết điểm của bạn thì nên khắc phục ngay thôi, họ viết những hàm core này rất cẩn thận, vì sợ rằng mỗi trình duyệt có 1 chút khác nhau. Các module đều dựa vào đây mà làm mà. Bạn nên xem thử xem họ viết gì trong các thư viện kia, cái nào học hỏi được thì nên học hỏi chứ . |
|
Blog: http://hontap.blogspot.com
Tải phần mềm miễn phí: http://www.taiphanmem.org |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
06/04/2008 09:01:48 (+0700) | #6 | 123473 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Nói như vậy có nghĩa bạn cũng đã bỏ thời gian ra tìm hiểu và làm việc với các framework đó thì phải. Chưa biết chừng learn2hack là tiền bối của keyboardDigger cũng nên .
Việc tận dụng thế mạnh của Regular expression để làm gọn cú pháp đến mức tối đa theo kiểu của jQuery quả thật rất ấn tượng, giúp lập trình viên có thể "play with HTML" một cách thoải mái. Mình đánh giá cao khả năng đó, nhưng thực sự mình không có ý định cạnh tranh với jQuery về độ ngắn của cú pháp.
Mục tiêu của mình khi làm DHTiny là rút gọn cú pháp trong đa số các trường hợp soạn thảo JS thông thường, cải thiện và đơn giản hóa khả năng làm việc với prototype và class (Đây mới thực sự là cái có ý nghĩa đối với mình). Rất nhiều những thứ nho nhỏ kiểu hàm tiện ích thì DHTiny cũng đã có tạm đủ. Khi đã sử dụng DHTiny để lập trình hướng đối tượng, hầu hết các thành phần được tạo ra trên document body đều có thể truy cập qua con trỏ trực tiếp đến đối tượng. Mình thấy trong trường hợp này thực sự không cần thiết phải gọi ra 1 selector phức tạp (sau khi đã học thuộc đặc thù cú pháp kiểu CSS và XPath), khởi động 1 parser để phân tích câu lệnh, sau đó mới làm việc trên tập kết quả trả về.
Và cuối cùng, ai đó có thể cân nhắc giữa việc import một fat-framework với vài ngàn dòng lệnh và import một thư viện bé xíu chỉ có dưới 400 dòng chứa đa số các chức năng cơ bản. Viết ra một parser cho selector không phải là quá khó khăn, nhưng cũng không thể làm xong trong 1 sớm 1 chiều được. Thực sự chỉ cộng tổng kích thước của các hàm find(), filter() và 1 hàm nào đó trong phần event handling của jQuery đã đủ để mình hoàn thiện core của DHTiny rồi.
Mình sẽ giữ core của nó sao cho luôn xứng với cái tên DHTiny. Khi giỡ bỏ mọi utility module, nó sẽ luôn là món ăn none-fat ưa thích trong các ứng dụng mình viết .
Cảm ơn learn2hack rất nhiều vì đã thường xuyên góp ý cho topic này! |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
06/04/2008 11:46:57 (+0700) | #7 | 123505 |
|
SuperChicken
Elite Member
|
0 |
|
|
Joined: 11/07/2006 18:31:27
Messages: 635
Location: bottom of hell
Offline
|
|
Wow, một ý tưởng rất đáng được khen ngợi, 1 framework cho JS của Việt Nam
Mình thì không rành JS lắm, trình độ thì cũng chỉ ở mức sử dụng 1 vài tiện ích cơ bản của các framework như jQuery hay mootools. Hồi trước thì mình thích mootools hơn vì thấy nó có quá nhiều tiện ích và được đánh giá là framework dễ dàng extend. Nhưng sau 1 thời gian sử dụng thì thấy hình như performance có vấn đề, chỉ trích tối thiểu những gì mình dùng rồi (và cũng chỉ dùng 1 ít effect) nhưng trang web bắt đầu ì ạch.
Nếu được thì sau khi có phần core, bạn có thể implement thêm 1 ít tiện ích cho mọi người dùng được không . Rất mong chờ sự ra đời của DHTiny (không cạnh tranh về sự tiện ích với các framework khác thì mình cạnh tranh về performance bạn nhé ) |
|
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
07/04/2008 12:52:06 (+0700) | #8 | 123758 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Phần 2: Gọi hàm của DHTiny từ 2 scope: Global scope và Object scope.
Trong phần này, mình sẽ bàn đến vấn đề overload hàm trong DHTiny để các hàm của DHTiny vừa có thể được gọi linh hoạt ở nhiều ngữ cảnh.
Overload là khả năng không được hỗ trợ trong javascript. Tuy nhiên nếu ta tận dụng khả năng truyền tham số cho hàm khá "phóng khoáng" của JS, kết hợp với kiểm soát danh sách tham số đầu vào thì mọi thứ đều sẽ trở nên đơn giản.
Khi sử dụng DHTiny, ta có thể viết theo cách như sau:
Code:
// Cách 1: Gọi hàm của DHTiny tạo ra một đối tượng trong document body
var myDiv = $ce("div", {id:"myDiv", html:"I am a DIV element"}).$jump($body);
// ..... rồi add event handler cho đối tượng
myDiv.$aev("mousedown", function() {
$set(this, {html: "I have been clicked", color: "black", bg: "#505050", bounds:[0,0,10,10]});
});
// Truy cập đến element theo ID ra và xử lý theo cách của DHTiny
$id("myElement").$set( { html : "Funny text", style: {opac:30, bg: "blue"} });
Cách viết khác:
Code:
// Cách 2:
var myDiv = $ce("div", {id:"myDiv", html:"I am a DIV element"});
$jump(myDiv, $body);
// ..... rồi add event handler cho đối tượng
$aev(myDiv, "mousedown", function() {
$set(this, {html: "I have been clicked", color: "black", bg: "#505050", bounds:[0,0,10,10]});
});
// Truy cập đến element theo ID ra và xử lý theo cách của DHTiny
$set( $id("myElement"), { html : "Funny text", style: {opac:30, bg: "blue"} });
So sánh 2 cách viết, ta thấy cùng 1 hàm của DHTiny có thể được gọi ra ở 2 scope khác nhau: global scope (cách 2) và object scope (cách 1). Có khả năng đó chính là vì mỗi hàm của DHTiny khi xây dựng đều đã tính đến việc overload.
+ Ở global scope: hàm của DHTiny được gọi ra 1 cách tự nhiên - line by line, object được truyền vào với tư cách là tham số đầu tiên.
+Ở object scope: hàm của DHTiny được gọi theo kiểu inline, tham số object sẽ bị lược bỏ cho gọn.
Ta xem thử source code của một hàm trong DHTiny đã được overload cho 2 mục đích kể trên. Dưới đây là hàm thiết lập thuộc tính độ sáng (opacity) cho một đối tượng.
Code:
// _id có thể là ID của đối tượng, hoặc con trỏ đến đối tượng
function $_opac(_id, _opac) {
if (arguments.length == 1) // Nếu chỉ có 1 tham số, tức đang gọi ở object scope
return $_opac(this, _id); // ... thì chuyển sang global scope làm việc
else {
_id = $id(_id); // Truy cập đối tượng
// Đặt thuộc tính độ sáng, thỏa mãn luôn yêu cầu cross-browser
$set(_id.style, {opacity: _opac/100,
MozOpacity: _opac/100,
KhtmlOpacity: _opac/100,
filter: "alpha(opacity=" + _opac + ")"});
return _id;
}
}
Khi sử dụng, ta có thể gọi:
Code:
hoặc:
Code:
Đến phần này, một câu hỏi sẽ nảy sinh: Làm thế nào để một đối tượng có thể gọi inline loạt hàm của DHTiny theo cách như vậy? Chắc không quá khó để bạn tìm ra câu trả lời: phải sử dụng 1 hàm để "ép prototype" cho đối tượng đó.
Cách làm của DHTiny như sau:
Đầu tiên, khai báo loạt hàm sẽ được kiểm soát bởi DHTiny (Có thể coi là một namespace), loạt hàm này đã được overload để gọi ở cả global scope và object scope:
Code:
var DHTObjFuncs = {
$ac : $ac, $rc : $rc, $jump: $jump, // DOM methods
$innerTxt: $innerTxt, $_innerTxt:$_innerTxt,
$aev: $aev, $rev: $rev,..... // Event handling methods
$set: $set, $_set: $_set, // Core
$css:$css, $opac:$opac, $_opac:$_opac,
$show: $show, $hide:$hide, $hideContent: $hideContent, $showContent: $showContent,
$extend: $extend
......
}
Viết 1 hàm "ép prototype", "chuyển" toàn bộ các hàm inline của DHTiny vào 1 object
Code:
function $DHT(obj) {
if ($null(obj) || obj.$ac) return obj; // Already be a member of DHT family
for (var x in DHTObjFuncs) obj[x] = DHTObjFuncs[x];
return obj;
}
Định nghĩa các hàm thành viên:
Code:
function $ac() {...}
function $jump() {...}
function $css() {...}
function $tag() {...}
function $class() {...}
Khi viết các hàm không phục vụ gọi inline, nhưng có vai trò như "start point" của DHTiny, phải luôn chú ý đến việc gọi $DHT để "vỗ béo" đối tượng:
Code:
function $id(_id) {
return $DHT((typeof _id == "string") ? $doc.getElementById(_id) : _id);
}
function $ce(_tag, _props) {
return $DHT($set(document.createElement(_tag), _props));
}
...
Chính nhờ đó mà ta có thể gọi ra 1 chùm hàm như trong các ví dụ đã nêu:
Code:
$id("myDiv").$[hàm 1]().$[hàm 2].$[....]().....
$ce("textarea", {prop1: value1, prop2: value2, .....}).$[hàm 1]().$[hàm 2].$[....]().....
Một cách khác: ta dùng trực tiếp $DHT() khi muốn đối xử với một đối tượng bất kỳ như một "member của DHTiny". Ví dụ: D là con trỏ đến một DIV element, ta add loạt element vào đó, sau đó đưa D vào nằm trong document body như sau:
Code:
$DHT(D).$ac(myDiv1, myDiv2, myDiv3).$jump($body) ;
Mình đã kiểm tra lại performance của DHTiny sau khi khởi tạo và làm việc với hàng trăm element trên document body trống rỗng. Kết quả khá khả quan, tốc độ không bị chậm đi chút nào so với cách viết các câu lệnh JS nguyên thủy. Tuy rằng vấn đề memory leak mình chưa để tâm giải quyết, song tạm thời như vậy là có thể chấp nhận được. Đến đây mình tạm yên tâm với vấn đề performance và tiếp tục thực hiện các bước sau. |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
07/04/2008 15:18:56 (+0700) | #9 | 123774 |
|
learn2hack
Elite Member
|
0 |
|
|
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
|
|
Cám ơn keyboardDigger đã khen quá mình lên, mình mới chỉ làm quen với những framework JS này được không lâu, và hiểu biết còn rất ít ỏi. Bằng chứng của sự hiểu biết ít ỏi là đây
Mình thấy phương thức gọi hàm như ý của bạn rất hay, cách này rất thuận tiện cho người viết code. Thực tế có thể thấy 2 cách gọi hàm này nhắm vào 2 hướng: 1 theo phong cách lập trình hướng đối tượng, 1 theo phong cách lập trình hàm. Cả 2 đều có lúc cần phải dùng đến, cho nên cách viết hàm như vậy rất thông minh.
Có điều, mình chưa hiểu lắm về phương thức ép prototype của bạn. Theo như mình hiểu, và cũng như bạn đã giải thích ở post 1, thì để có thể gọi inline 1 hàm chúng ta chỉ cần return chính bản thân nó sau khi gọi là được. Việc làm phức tạp như bạn ở trên, và giải thích của bạn khiến mình không hiểu lắm, bạn có thể nói rõ ràng hơn 1 chút được không? |
|
Blog: http://hontap.blogspot.com
Tải phần mềm miễn phí: http://www.taiphanmem.org |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
08/04/2008 01:23:29 (+0700) | #10 | 123868 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Thuyết minh mà không làm người khác hiểu được thì phần nhiều lỗi lại nằm ở phía người trình bày bạn ạ . Mình xin được trình bày rõ hơn như sau:
Trong các ngôn ngữ lập trình hướng đối tượng như C++ hay Java, prototype của các class được khai báo một cách tường minh và nhất quán. Các instance của class chỉ có những thuộc tính và phương thức nằm trong prototype của class mà thôi.
Tuy nhiên với ngôn ngữ prototype như JS, mỗi class, ngay cả mỗi đối tượng có thể xem như có prototype riêng. Ta được quyền mở rộng, sửa đổi, loại bỏ các thành phần trong prototype một cách tương đối thoải mái, đôi khi gần như là "tùy tiện".
Ví dụ với một đối tượng myClass có prototype được định nghĩa như sau:
Code:
function myClass () {
this.name = "";
this.sayHello = function() { alert("Hello, my name is " + this.name)};
}
Theo cách truyền thống, từ instance ta gọi được thuộc tính và phương thức từ prototype của myClass
Code:
var myInstance = new myClass();
myInstance.name = "myName";
myInstance.sayHello();
Nhưng không dừng lại ở đó, nếu từ myInstance ta muốn gọi những phương thức, thuộc tính mà mình "bỗng chợt nghĩ ra" ở chỗ nào đó trong thân chương trình thì phải làm thế nào?
Trước mắt mình có thể giới thiệu 3 con đường:
// 1. Mở rộng prototype cho native Object của JS
Code:
Object.prototype.sayWelcome = function () { alert("Welcome to DHTiny's world!")};
// 2. Mở rộng prototype cho myClass
Code:
myClass.prototype.showDemo = function () { alert("Let's take a look on some demos!")};
// 3. Mở rộng prototype cho chính myInstance, đây là cách mà hàm $DHT() làm
Code:
myInstance.guestName = "";
myInstance.sayGoodbye = function () { alert("Goodbye for now, " + this.guestName + "!")};
// Xong! Ta có thể gọi những thành phần mới như sau:
Code:
myInstance.sayWelcome();
myInstance.showDemo();
myInstance.guestName = "myGuest";
myInstance.sayGoodbye();
Bạn có thể thấy: những phương thức sayWelcome(), showDemo(), sayGoodbye() và thuộc tính guestName chưa từng được định nghĩa trong myClass, tuy nhiên lại có thể được gọi ra từ thể hiện của nó là myInstance.
Ở cách làm 1 và 2, ta bổ sung cái mới cho myInstance bằng cách nhét thẳng những cái mới đó vào trong prototype của lớp mà nó kế thừa. Lý do có thể nói nôm na là khi khai báo myInstance, cả hai constructor của Object và myClass đều được gọi ra, do đó Object và myClass mà thay đổi thì myInstance cũng thay đổi.
Ở cách làm thứ 3 làm lộ rõ nhất đặc thù của ngôn ngữ prototype: bạn có thể "ung dung" gán thuộc tính, gọi phương thức từ đối tượng cụ thể, như thể chúng đã có từ trước.
Đến đây, chắc hẳn bạn đã rõ cái mà hàm $DHT() đã làm. Mình gom toàn bộ các hàm inline vào một tập hợp, sau đó gắn toàn bộ con trỏ có trong tập hợp đó vào 1 object cụ thể nhằm tái sử dụng lâu dài. Việc gán như vậy ban đầu làm nảy sinh mối lo về việc phát sinh con trỏ nặc danh, con trỏ lặp vòng và tốc độ xử lý. Tuy nhiên mình đã kiểm tra lại và tạm thời không thấy vấn đề gì cả. |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
08/04/2008 14:14:06 (+0700) | #11 | 123997 |
|
learn2hack
Elite Member
|
0 |
|
|
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
|
|
Giờ thì mình đã hiểu cách thức bạn làm. Mấu chốt của nó nằm ở hàm $DTH này:
Code:
function $DHT(obj) {
if ($null(obj) || obj.$ac) return obj; // Already be a member of DHT family
[color=yellow]for (var x in DHTObjFuncs) obj[x] = DHTObjFuncs[x];[/color]
return obj;
}
Hàm này có nhiệm vụ duyệt qua đối tượng, tìm xem các method của nó có được khai báo trong danh sách hàm hay không (tức là có thể cho phép gọi inline hay ko) và thêm vào các hàm đó cho đối tượng đang xét khi cần thiết.
Sau đó, để đảm bảo cho đối tượng của mình được phép sử dụng những hàm đó, bạn dùng cách ép nó vào hàm $DHT ở những hàm gọi là start point (tức là những hàm cơ bản, trả về 1 đối tượng nào đó) như $id.
Nguyên nhân bạn phải làm thế này là do có vô vàn loại đối tượng khác nhau được tạo ra (bạn để thoải mái chuyện này), và bạn muốn đối tượng nào trong chúng cũng có thể sử dụng các hàm inline này được.
Về xuất phát điểm này của bạn khá khác so với jQuery và prototype. Họ thay vì cho phép các đối tượng thoải mái như bạn, thì lại gom hết chúng vào 1 hàm đầu não là $; có nghĩa là muốn truy cập đến cái nào cũng cần phải thông qua hàm $. Cho nên, việc thiết kế inline có lẽ sẽ đơn giản hơn của bạn rất nhiều, vì không cần thiết phải ép prototype nữa.
Đang chờ phần tiếp theo của bạn, xây dựng kiểu này rất thú vị và học hỏi được rất nhiều . |
|
Blog: http://hontap.blogspot.com
Tải phần mềm miễn phí: http://www.taiphanmem.org |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
09/04/2008 00:20:54 (+0700) | #12 | 124048 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Bạn nói đúng, cái đó vốn là điểm tớ đã cân nhắc về DHTiny. Nếu làm như mình, thiết kế inline phải để tâm đến từng hàm một. Trong khi đó jQuery chỉ làm việc với những gì đi qua constructor của nó, rồi sau đấy "quên luôn cho nhẹ người" .
Mặc dù làm theo cách của mình trông có vẻ mệt mỏi, nhưng cũng có một chút cái lợi nhất định.
Mình đã biến loạt hàm cơ bản thành start point để người lập trình có thể không cần để tâm đến sự tồn tại của hàm $DHT() nữa. Và một khi 1 đối tượng đã từng bị truyền như 1 tham số qua start point thì trừ phi bị delete, nó sẽ luôn có đủ tính năng của DHTiny. Bên cạnh đó loạt hàm DHTiny có thể gọi ở global scope, hoàn toàn không cần quan tâm đến việc có phải ép prototype hay không. |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
18/04/2008 12:52:37 (+0700) | #13 | 125986 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Phần 3: Lập trình hứớng đối tượng với DHTiny
Mình hơi bận bịu và stress trong dịp vừa rồi, nên mãi giờ mới viết được bài tiếp theo giới thiệu về DHTiny.
Trong phần này, ta sẽ nghiên cứu một chút về việc lập trình hướng đối tượng trong JavaScript, và DHTiny hỗ trợ lập trình hướng đối tượng như thế nào.
Với đặc điểm của một ngôn ngữ prototype, mình có thể phát biểu như sau về javascript: "Trong javascript, mọi object và class đều có thể xem như interface".
Quả như vậy, không có một giới hạn nào đặt ra cho người lập trình JS khi làm việc với thuộc tính hay phương thức của object hay class. Ta có thể mở rộng hay thay đổi các thuộc tính, phương thức đó một cách hết sức linh động.
Tận dụng đặc điểm đó, mình đã chuẩn bị sẵn một nhóm hàm hỗ trợ lập trình hướng đối tượng trong DHTiny. Với những hàm đơn giản này, người lập trình không chỉ thực hiện được các thao tác quen thuộc như extending, implementing, overiding..., họ còn có thể làm được nhiều thao tác khác mà chỉ có ngôn ngữ prototype mới có.
Nhóm hàm mình đã viết:
+ $newClass: tạo ra 1 class mới
+ Function.prototype.inherit: từ class lớp dưới gọi 1 hàm từ interface mà nó "thừa kế".
+ $extend: hàm cho phép mở rộng đối tượng/class từ bất kỳ một interface có sẵn nào
+ $inherited(className): trả về tập các interface mà class "className" đã "thừa kế"
Biến toàn cục: $instancesOf["className"] lưu trữ loạt con trỏ đến các instance của class "className"
Biến mặc định của mọi class: Function.protype.className lưu trữ tên class dưới dạng string. Đây cũng chính là thuộc tính được sử dụng để tham chiếu đến các class trong CSS.
Trước hết, mời bạn nhìn qua một đoạn code theo kiểu của DHTiny:
Code:
// Tham số của hàm $newClass(_name, _interfaces, _prototype) - tạo một class mới:
// +_name: tên class sắp tạo (string)
// +_interfaces: mảng chứa danh sách các "interface" mà class này sẽ "thừa kế" theo thứ tự.
// null nếu ko có gì
// + _prototype: các thuộc tính, phương thức của class
$newClass("A", null, {
x: 10,
y: 20,
_constructor: function(_name) { // Contructor của class
this.name = _name;
alert("Hello, " + _name);
},
doSomething: function() {
alert(this.name +" is doing something");
}
});
$newClass("B", A, {
_funnyB : "laugh",
_constructor: function(_name) { // Contructor của class
this.inherit(A, "_constructor", [_name]);
alert("Welcome to DHTiny's world, " + _name);
},
doSomething: function() {
alert("Mr./Mrs. " + this.name + " is doing something");
},
saySomething: function() {
alert("Hey, take a look at this!");
}
});
E = { _funnyE: "VERY BIG LAUGH"}
$newClass("C",[A,B,E],{_funnyC : " Big laugh"});
var a= new A("aName"); // Output: "Hello, aName"
var b = new B("bName"); // Output: "Welcome to DHTiny's world, bName"
var c = new C("cName"); // Output: "Welcome to DHTiny's world, cName"
alert(a.x == b.x); // Output: "true"
alert(a.y + " " + b.y); // Output: "20 20"
a.doSomething(); // Output: "aName is doing something"
b.doSomething(); // Output: "Mr./Mrs. bName is doing something"
c.doSomething(); // Output: "Mr./Mrs. cName is doing something"
alert(c._funnyB + " " + c._funnyC + " " + c._funnyE); // Output: "laugh Big laugh VERY BIG LAUGH"
$instancesOf["B"][0].doSomething(); // Output: "Mr./Mrs. bName is doing something"
alert($inherited(C).length); // Output: 3, số lượng interface mà C thừa kế
Chắc chắn nhìn đoạn code trên, nhiều người đã hiểu ngay cái mà DHTiny đã làm. Tuy nhiên, để làm cho mọi thứ rõ ràng hơn, ta hãy cùng bàn thêm 1 chút về JS.
Trong JavaScript, mỗi Class được định nghĩa bắt đầu bằng việc gọi constructor Function. Các cách viết dưới đây là hoàn toàn giống nhau:
Cách viết phổ biến
Code:
function ClassA() {
this.className = "A"; // Gán giá trị mặc định cho thuộc tính
this.sayHello = say; // Trỏ đến một hàm ngoại vi
this.sayGoodbye = function() { // Định nghĩa luôn một hàm cục bộ
alert("Thanks for using DHTiny! See ya!");
}
}
function say() {
alert("Welcome to DHTiny's world!");
}
var a = new ClassA(); // Khai báo instance
alert(a.className);
a.sayHello();
b.sayGoodbye();
Một cách viết thoải mái hơn:
Code:
// Mọi thuộc tính đều có thể "tiền trảm hậu tấu", tức là có thể khai báo bất kỳ lúc nào sau khi Function constructor được gọi
A = new Function();
A.prototype.className = "A";
A.prototype.sayHello = say;
A.prototype.sayGoodbye = function () {.... }
[code]
Một vài điểm cần chú ý của việc thao tác trên instance và khai báo/định nghĩa thuộc tính của class sau khi đã tồn tại instance của class
- Trước hết, đương nhiên sau khi gọi [b]new[/b] để tạo ra 1 instance mới, instance của class được thừa kế toàn bộ những gì có trong prototype của class.
- Mọi thuộc tính, phương thức kế thừa từ class đều có thể bị overwrite ở phạm vi instance
- Những thuộc tính, phương thức không bị overwrite sẽ bị thay đổi một cách "động" theo prototype của class.
Bạn xem ví dụ bên dưới:
[code]
// Khai báo class A và định nghĩa các thuộc tính, phương thức
var A= new Function();
A.prototype.x = 10;
A.prototype.y = 20;
A.prototype.z = function() {alert("I am Z")};
// Khai báo một instance để làm ví dụ
var a = new A();
// Gọi thử các thuộc tính, phương thức từ instance
alert("x="+a.x+ ", y=" + a.y); // Kết quả: x=10, y=10
a.z(); // Kết quả: "I am a Z";
a.x = 123; // Thử thay đổi thuộc tính x ở instance
A.prototype.x = 200; // Thử thay đổi thuộc tính x ở prototype của class
A.prototype.y = 400; // Thử thay đổi thuộc tính y ở prototype của class
A.prototype.z = function() {alert("I am new Z")}; // Thử thay đổi phương thức z ở prototype của class
alert("x="+a.x+ ", y=" + a.y); // Kết quả: x=123, y=400
a.z(); // Kết quả: "I am new Z"
// Như vậy, x đã bị overwrite tại instance, còn y và z thì bị thay đổi tự động theo prototype của class A
Đến đây, bạn thậm chí còn có thể viết được những hàm của DHTiny mà mình đề cập ở đầu. Việc liên tục gán A.prototype.[something] = .... khiến ta hình dung đến hàm hạt nhân $set của thư viện.
Hàm $newClass có thể viết na ná như sau:
Code:
$newClass = function(_name, _interfaces, _props) {
window[_name] = function() {
if (this._contructor) // Luôn gọi contructor đầu tiên, hiển nhiên mà :-D
this._contructor.apply(this,arguments);
// Bổ sung con trỏ instance vào danh sách quản lý
if ($null($instancesOf[_name])) $instancesOf[_name] = new Array();
$instancesOf[_name].push(this);
};
// Thừa kế interface theo thứ tự <-- Chỉ tham khảo thôi nhé, cái này ko an toàn đâu
for (var i =0; i < _interfaces.length; i++)
$extend(window[_name], _interfaces[i]);
}
// Bạn chỉ cần viết dưới đây cũng có thể chạy được rồi, tuy nhiên DHTiny còn có bổ sung chút technique nho nhỏ nữa
$extend = function (_class, _interface) {
if ($isFunction(_interface))
$set(window[_name].prototype, _interface.prototype);
else
$set(window[_name.prototype, _interface);
}
Các hàm $inherited() và Function.prototype.inherited() nhìn từ đây sẽ là hết sức đơn giản. Giờ khuya quá rồi, mình ngủ cái đã, ko còn sức viết tiếp nữa |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
18/04/2008 17:05:33 (+0700) | #14 | 126005 |
|
learn2hack
Elite Member
|
0 |
|
|
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
|
|
Đợi mãi giờ bạn mới post tiếp .
Phần này giống như bạn đang tự mở rộng JS ra để nó làm việc tốt hơn trong việc thừa kế. Mình thấy nó khá hay, nhưng ko rõ có thực sự cần thiết ko. Vì JS là ngôn ngữ phía Client, nó tuy có OOP nhưng mang 1 đặc thù rất khác các ngôn ngữ phía Server là nó làm việc trên những đối tượng DOM và tương tác với client là chủ yếu (mặc dù nó không hạn chế những thứ khác). Việc mở rộng như bạn thế này giống như tạo cho nó có khả năng của 1 ngôn ngữ OOP mạnh giống các ngôn ngữ OOP khác (PHP, Java, ...), nhưng mình băn khoăn là nó ứng dụng như thế nào ở phía client. Bạn có thể chỉ vài VD (ko cần code đâu, hướng là được) mà áp dụng cái này 1 cách hiệu quả không? |
|
Blog: http://hontap.blogspot.com
Tải phần mềm miễn phí: http://www.taiphanmem.org |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
19/04/2008 00:20:31 (+0700) | #15 | 126054 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Một câu hỏi rất giống với những gì mình tự hỏi khi bắt đầu làm việc với các AJAX component! Mình thấy khó hiểu, thậm chí là hài hước vì mình nhìn nhận JS như thế một phương tiện để "bày biện đồ đạc" trên document body là chính, đâu có quá cần thiết phải extend, implement làm gì cho nhọc.
Nhưng mọi thứ nó có khác đi nhiều khi mình thử bắt đầu nghĩ lại, làm lại. Mình thử viết những component theo đúng kiểu lập trình hướng đối tượng nguyên nghĩa kiểu Java (Tức là extend được 1 super duy nhất, implement được nhiều interface), thì thấy code mình viết có khả năng tái sử dụng và mở rộng mạnh hơn rất nhiều, đồng thời quản lý đối tượng hết sức tiện lợi.
Mình chưa post được demo, nhưng xin lý giải bằng ví dụ đơn giản như sau (Có lẽ có ví dụ tốt hơn nhiều, nhưng tạm thời mình chỉ đưa ra được thế này ).
+ Đầu tiên, mình có 1 class là Post. Một instance của nó là một khu vực hiển thị một bài viết nào đó lấy từ database. Nó đã được bổ sung thông tin CSS khá hoàn chỉnh.
+ Bước 2: Mình viết thêm 1 class là ContentUpdater, cứ sau 1 phút nó tự động request bài viết mới nhất trong database và kéo về browser.
+ Bước 3: Với chỉ vài dòng code, chi cần tạo ra 1 class mới extend Post và implement ContentUpdater, mình được luôn 1 class tên là LastPost. Mỗi instance của nó vừa có trình bày đẹp như Post vừa có khả năng tự cập nhật thông tin như ContentUpdater.
+ Bước 4: Sử dụng class LastPost, mình sẽ thoải mái đặt các control là instance của class này lên trang web, với ý nghĩa là các bài viết mới nhất từ các box.
- Nếu muốn có tính năng tự đổi background sau 3 phút một (Chỉ là ví dụ thôi , ai lại làm thế!), mình chỉ cần gọi 1 lệnh gán duy nhất nhưng sẽ gây ảnh hưởng đến toàn bộ các instance đang tồn tại. Tương tự như vậy, nếu mình muốn thay vì xuất hiện tắp lự trên màn hình, các instance này từ từ nối đuôi nhau trải xuống phía đáy của màn hình, thì mình cũng chỉ viết lại/bổ sung 1 hàm show() là xong cho mọi đối tượng đang tồn tại.
- Nếu muốn truy cập đến một bài viết bất kỳ, thay đổi một thành phần bất kỳ nào đó của nó (Ví dụ như titlebar, bottombar, content,...), mình chỉ cần gọi thành phần qua truy vết từ con trỏ nằm trong mảng quản lý. Rõ ràng là nhanh hơn rất nhiều so với việc cần mẫn đi query đối tượng.
- ... nhiều khả năng kế thừa, mở rộng và gây phản ứng dây chuyền khác...
Nếu bạn xem cái trang chủ mình viết dưới đây, bạn sẽ thấy đây là đống code không dễ để có thể tái sử dụng (Do mình viết cách đây 5 tháng, lúc mới học JS , nhiều chỗ bị bắt đưa Array ngớ ngẩn vào). Nếu làm theo kiểu ví dụ trên đây, theo bạn, bạn sẽ viết gọn lại chỉ còn bao nhiều? 50% chứ ? Mình cũng không chắc là DHTiny có thể làm gọn lại được ít hơn không, chỉ biết rằng source code sẽ cực kỳ sáng sủa và có khả năng tái sử dụng mạnh.
http://hows-corp.jp (Chạy tốt trên cả IE, FF, Opera, Mac Safari,...
Mình chắc chắn sẽ show loạt demo nhỏ về các khả năng có sẵn ủa DHTiny lên trên này sớm kèm theo lý giải cách làm. Lý do của việc chưa show demo được là vì mình phải xác nhận bản quyền cho chắc chắn đã. Khi xem demo thì có lẽ ai đó không xem nổi source code của bản core (Tạm thời chưa open source được nên mình đã mã hóa), nhưng source code của các component thì xem thoải mái, tương đối bé và dễ hiểu . Mình nhất định sẽ open source DHTiny để mọi người cùng sử dụng và góp ý . |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Cùng xây dựng thư viện javascript DHTiny từ đầu |
19/04/2008 07:18:53 (+0700) | #16 | 126146 |
|
learn2hack
Elite Member
|
0 |
|
|
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
|
|
Mình mới chỉ có mang máng khái niệm về cách sử dụng này, cho nên cũng chưa nắm rõ lắm. VD bạn lấy đặc trưng quá, vì hầu hết vấn đề OOP trong JS đều nhắm đầu tiên vào AJaX (cả trong các thư viện khác cũng vậy). Nếu có 1 demo đơn thuần object thì tốt hơn.
Vấn đề bản quyền bạn lo cũng đúng, nhưng bạn có thể đăng kí tại SF hoặc Google Project (giống jQuery), sau đó hãy public. Cũng nhanh gọn, không cần lo host/domain đâu.
Phần sơ khởi thì tạm ok rồi , mình e là càng lên cao càng nên có VD thì sẽ tốt hơn. |
|
Blog: http://hontap.blogspot.com
Tải phần mềm miễn phí: http://www.taiphanmem.org |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
25/04/2008 07:12:03 (+0700) | #17 | 127417 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Mình đã dọn nhà cho DHTiny đến Google code, mời các bạn cùng xem qua và góp ý:
http://code.google.com/p/dhtiny/
Nếu bạn có thể tham gia cùng mình phát triển thư viện, xin mời đăng ký làm member của dự án, đồng thời join vào mail group của DHTiny tại:
http://groups.google.com/group/dhtiny
Mình sẽ nhanh chóng bổ sung loạt demo và viết lại API document cho cẩn thận hơn cho nhiều người sử dụng.
Rất mong nhận được sự ủng hộ của tất cả mọi người! |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
26/04/2008 05:08:30 (+0700) | #18 | 127596 |
hopham86
Member
|
0 |
|
|
Joined: 25/04/2008 12:56:06
Messages: 3
Offline
|
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
08/05/2008 12:18:47 (+0700) | #19 | 129600 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
DHTiny version 0.5.1: http://code.google.com/p/dhtiny
Phiên bản mới nhất của DHTiny (0.5.1) đã được upload lên Google code, bao hàm những điểm mới sau đây:
+ Bổ sung loạt demo nhỏ (Tạm thời có Webtop đơn giản - giả Desktop trên nền web, Form control, TreeView Control , hiệu ứng Drag&Drop và Animation). Rấtt nhiều khỏan mục còn chưa hòan tất, đang được chỉnh sửa và nâng cấp dần)
+ Bổ sung và bố trí lại $DHTiny namespace
+ Bổ sung 1 số hàm tiện ích phục vụ cho lập trình hướng đối tượng
Mục tiêu trong version 0.5.2 (Dự kiến ra mắt vào cuối tháng 5/2008):
+ Hòan tất Webtop demo để giúp người dùng nhanh chóng hiểu ra những gì mà DHTiny đang có. Khoản này mình sẽ làm cẩn thận để tránh bị chê là "keo kiệt" và "lề mề" trong khoản show demo .
+ Hòan thiện $DHTiny namespace nhằm tránh sửa đổi lời gọi hàm về sau.
+ Hòan thiện một số hàm quan trọng hiện đang còn dang dở (VD: $getElems() hay $insertProc())
+ Bỏ bản nháp và viết lại DHAnimation cho thật gọn và hợp lý, đồng thời bổ sung nhiều hiệu ứng trực quan khác
+ Tiếp tục bổ sung lọat hàm cross-browser vào $DHTiny
Hiện mình đang viết DHTiny trong những khoảng thời gian trích rút từ giờ nghỉ, đâm ra công việc tiến triển tương đối chậm và vất vả . Nếu có một số bạn ưa thích lập trình AJAX cùng tham gia phát triển với mình thì tốt quá . Nếu việc lập trình core là rắc rối và nhàm chán, các bạn có thể hỗ trợ mình phát triển phần plugin cũng được .
Rất mong lại tiếp tục nhận được sự ủng hộ từ phía các bạn! |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
13/05/2008 11:14:19 (+0700) | #20 | 130276 |
|
SuperChicken
Elite Member
|
0 |
|
|
Joined: 11/07/2006 18:31:27
Messages: 635
Location: bottom of hell
Offline
|
|
Sao 404 rồi bạn? Đang định click thử xem nó ra sao rồi. Cũng muốn tham gia nhưng trình độ JS hơi bị chuối nên thôi |
|
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
13/05/2008 12:26:27 (+0700) | #21 | 130290 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
13/05/2008 22:48:23 (+0700) | #22 | 130338 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Tạm thời bộ demo thì mình hoàn toàn ko có thì giờ để bổ sung và trang trí lại. Tuy nhiên nếu ai đó muốn dạo nhanh qua demo của thư viện thì xin mời xem qua loa mấy cái nho nhỏ sau đây:
http://***/duc/dhtiny/demos/treeview.htm <-- (Hết sức xin lỗi cả nhà, mình phải xóa cái link này hơi gấp)
http://***/duc/dhtiny/demos/webtop.htm <--- Đây chỉ là bản nháp cũ (Image và code đều ở hơi thô kệch, mong các bạn thông cảm). Khi viết cái demo này, mục tiêu của mình trước nhất đơn giản là đưa ra một ví dụ trực quan để mọi người có thể nhận thấy: một webtop với đầy đủ những tính năng trình diễn trên desktop, trông có vẻ phức tạp nhưng có thể được viết gọn nhẹ như thế nào.
Để hình dung các demo sắp tới mình sẽ viết lại bằng DHTiny, mời các bạn xem qua:
+ Một cái webtop cũ rích, nhưng đã chạy được trên IE (Chỉ IE thôi nhé! Mình viết hồi mới học Ajax mà). Cái này có animation đơn giản, chức năng quản lý cửa sổ đầy đủ (Hỗ trợ phóng to thu nhỏ, resize, đáp ứng sự kiện chuột như trên Desktop):
http://***/duc/webvista/
+ Trang chủ của công ty, có một vài hiệu ứng nhỏ, chạy cross-browser:
http://www.****.jp <-- Có lẽ HVA forum kỵ dấu trừ (-) trong địa chỉ này cho nên ko cho phép link đến trang web. Bạn copy& paste vào address box để xem vậy |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
14/05/2008 14:15:14 (+0700) | #23 | 130465 |
|
learn2hack
Elite Member
|
0 |
|
|
Joined: 29/06/2006 16:32:37
Messages: 825
Offline
|
|
Trông khá ấn tượng đấy . Có vẻ như phần hạt nhân của thư viện này chỉ là cơ bản, giống như những gì bạn giới thiệu, còn những cái có thể dùng (như demo) thì phải dùng các thư viện kèm theo trong bộ source này rồi.
Nếu có thời gian, bạn viết documentation cho bọn chúng, hoặc là cách sử dụng, để mọi người vừa biết cách dùng, mà có phát triển tiếp thì cũng có tài liệu để phát triển.
Chúc vui vẻ. |
|
Blog: http://hontap.blogspot.com
Tải phần mềm miễn phí: http://www.taiphanmem.org |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
14/05/2008 20:02:47 (+0700) | #24 | 130475 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Chào bác learn2hack! Em đã viết sẵn document đầy đủ cho core rồi, nhưng bằng tiếng Anh (Tất nhiên là tiếng Anh củ chuối ) ). Tới đây em sẽ viết tutorial cẩn thận cho nó bằng tiếng Việt. Chắc copy mấy bài đã viết ở trong này paste vào quá. Bác ghé thăm trang Google Code thỉnh thoảng sẽ thấy 1 trang wiki mới ló ra đấy
Thanks bác đã quan tâm! |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
16/05/2008 00:26:14 (+0700) | #25 | 130697 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
HẾT SỨC XIN LỖI NHỮNG NGƯỜI QUAN TÂM VÌ SỰ ĐỘT NGỘT NÀY, NHƯNG MÌNH ĐÃ PHẢI TẠM ĐÓNG CỬA TRANG GOOGLE CODE CỦA DỰ ÁN VÌ GẶP PHẢI MỘT SỐ KHÓ KHĂN CHƯA THỂ GIẢI QUYẾT NGAY ĐƯỢC.
SẮP TỚI RẤT MONG LẠI CÓ DỊP PUBLISH PHIÊN BẢN ĐẦY ĐỦ CỦA DHTINY LÊN CHO MỌI NGƯỜI CÙNG GÓP Ý. TRONG THỜI GIAN NÀY, MỘT SỐ THÀNH PHẦN ĐƯỢC PHÁT TRIỂN BỞI DHTINY SẼ ĐƯỢC GIỚI THIỆU DƯỚI DẠNG CODE ĐÃ BỊ MÃ HÓA, CHỨ KHÔNG PHẢI OPEN SOURCE HOÀN TOÀN NHƯ TRƯỚC ĐÂY NỮA.
NẾU AI ĐÓ QUAN TÂM ĐẾN CÁCH THỨC PHÁT TRIỂN DHTINY HOẶC CẦN SOURCE CODE, CÓ THỂ BÀN LUẬN TRỰC TIẾP VỚI MÌNH, TRƯỚC HẾT LÀ QUA TOPIC NÀY. |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
16/05/2008 13:48:38 (+0700) | #26 | 130804 |
Cha này code chắc dữ quá nên giờ bị bệnh hoang tưởng. Một trong một số khó khăn chưa giải quyết là cái bệnh đó: Mình viết hay quá, tự nhiên đưa không lên làm gì, thà để bán sướng hơn. Tui nghĩ bạn đang có ý nghĩ đó vì hành động của bạn là đóng trang dự án trên Google code, bời vì tôi nghĩ mãi mà vẫn chưa ra cái lý do, khó khăn nào mà kiến bạn phải đóng bởi vì nó được đặt ở Google, chẳng phải tốn đồng nào. Còn nếu không có thời gian thì cứ để vậy, có chết ai đâu, việc gì phải đóng? Kết luận cuối cùng thì chỉ có thể là bệnh hoang tưởng. Nản, cứ tưởng sẽ có javascript library của người Việt, thôi thì cứ Prototype, JQuery, Mootools vậy. |
|
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
17/05/2008 01:43:59 (+0700) | #27 | 130849 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Chào anh bạn! Sự thật là mình không biết có nhiều người như anh bạn cũng quan tâm đến thư viện cho đến khi thư viện bị tạm thời đóng cửa. Đấy cũng là một tín hiệu vui, đồng thời cũng là một thử thách rất lớn đối với mình.
Cái mình viết ngay từ đầu đã là để cho cộng đồng, và bản thân nó cũng là kết quả của việc kế thừa và bổ sung những ý tưởng mới vào những sản phẩm cộng đồng khác.
Mình hoàn toàn không hề phải lo lắng về bản quyền của nó, vì từng dòng code là từng dòng mình nhào nặn ra. Tuy nhiên, cái vấn đề của mình nó lại nằm chính ở đó.
Số là ở công ty mình có 1 thư viện, nó cồng kềnh như thể Prototype nhưng logic thì ngớ ngẩn và performance đôi khi trở nên tệ hại khi viết component lớn. Chính vì không muốn code bằng cái thư viện rắc rối này, và cũng không muốn dùng bất kỳ một thư viện to đùng nào khác, mình đã viết DHTiny để khẳng định rằng code JS có thể được viết một cách thực sự nhẹ nhàng ngay từ trong lõi.
Có một điều thật đáng tiếc là mình lại đặt tên 2 hàm mình thích là $id và $ce giống với cách đặt tên hàm của thư viện công ty, mặc dù lõi hàm của DHTiny cực kỳ gọn gàng, logic giản dị, hoàn toàn khác biệt về mọi mặt. Thư viện của mình không được công ty sử dụng do họ muốn bảo vệ cái thư viện cũ (Do 1 lập trình viên lớn tuổi viết). Chính lẽ đó mà mình càng thấy thoải mái hơn khi đem open source DHTiny. Tuy nhiên khi 2 chú đồng nghiệp lắm điều ở công ty search được DHTiny trên mạng, nhìn thấy đó là sản phẩm free, liền ngay lập tức đổ lỗi cho mình là đem show kỹ thuật nội bộ ra ngoài. Mình mới sang công ty Nhật này làm được chưa đầy năm, các mối quan hệ còn rất rắc rối, nên tạm thời mình nhượng bộ đóng cửa thư viện để tranh luận ôn hòa với họ cái đã. Mình sẽ sớm mở cửa lại nó vì họ chắc chắn không có bằng chứng cho thấy mình đã làm lộ thư viện của họ. Cái khó khăn lớn hơn cả đối với mình lúc này chính là tính cả nể. Người Nhật khi đã đi chung trên 1 con tàu thì cực kỳ căm ghét những ai đánh mắt sang ngang, không nhắm toàn tâm vào mục tiêu chung của tập thể. Bạn cố gắng chờ mình vậy nhé!
Những tiền bối đi trước khi thấy mình gặp phải vấn đề này, đã khích lệ rất nhiều để mình cố gắng mau chóng giải quyết. Nhưng có lẽ câu nói của bạn cho rằng mình hoang tưởng còn có ý nghĩa thúc đẩy mạnh hơn đấy |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
17/05/2008 01:51:30 (+0700) | #28 | 130850 |
mR.Bi
Member
|
0 |
|
|
Joined: 22/03/2006 13:17:49
Messages: 812
Offline
|
|
@bietchetlien007: lúc người ta làm thì ko vào động viên tiếng, lúc người ta đóng thì la lối om xòm, của ngta, người ta thích đóng thì đóng, chả có cái lỗi gì ở đây để ông trách cả.
@keyboardDigger: ko sao, tớ down về cả 2 bản rồi .Dù sao cũng mong bạn sớm quay trở lại phát triển dHTiny cho cộng đồng |
|
All of my life I have lived by a code and the code is simple: "honour your parent, love your woman and defend your children" |
|
|
|
[Question] Re: Thư viện lập trình javascript DHTiny (Current ver: 0.5) |
18/05/2008 23:09:43 (+0700) | #29 | 131181 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Thư viện lập trình DHTiny đã quay trở lại .
Sau khi cân nhắc cẩn thận, mình quyết định tạm gạt bỏ sang một bên những lời chỉ trích vô căn cứ của một vài đồng nghiệp để tiếp tục open source sản phẩm này. Mình không dễ gì để sản phẩm mình làm ra bị cấm đoán bởi tay người khác được.
Hiện tại do cần phải sửa chữa lại một 2,3 tên hàm cho phù hợp với ý nghĩa và thống nhất trong mọi version, mình đã tạm cất các gói download đi để sửa chữa lại. Về cơ bản thay đổi là không lớn, do đó mọi người ráng chờ thêm 1 hôm nữa nhé.
Song song với việc đó, mình đang tranh thủ hết sức kho thời gian rảnh rỗi để viết dần loạt bài giới thiệu và thảo luận về kỹ thuật lập trình JS trên http://code.google.com/p/dhtiny. Nội dung sẽ không chỉ là về các vấn đề liên quan đến DHTiny từ sơ lược đến chi tiết, mà còn là những phát hiện nho nhỏ xung quanh AJAX mà mình có được trong quá trình xây dựng thư viện này.
Vì đây là một sản phẩm cho cộng đồng, nên thật sự mình rất mong nhận được comment của các bạn giành cho mỗi bài viết đó (Nhưng đừng quên login vào Google trước đã nhé ).
(P/Socument thì bây giờ mình dọn tạm lên cái chỗ free này: http://duck48ca.0moola.com/ ) |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
|
|
[Question] Thư viện lập trình javascript DHTiny (Current ver: 1.1.0) |
16/05/2011 21:54:42 (+0700) | #30 | 237254 |
|
keyboardDigger
Member
|
0 |
|
|
Joined: 27/03/2008 16:45:48
Messages: 26
Offline
|
|
Sau một thời gian làm nhiều loại công việc khác nhau, mình nhớ ra rằng: mình vẫn còn yêu JS ^_^
Mặc dù đã bắt thư viện DHTiny ngủ quên đến tận 2 năm liền, đánh mất nhiều cơ hội để nhận được sự ủng hộ của các anh em coder.
Tuy vậy mình hy vọng rằng với những idea mới, đống code cũ kỹ có thể sống lại và đi theo một hướng khác tích cực hơn, không nhất thiết phải cạnh tranh toàn diện với những ông lớn khác (jQuery, ExtJS).
Mời các bạn xem bài viết giới thiệu mới của DHTiny tại đây:
/hvaonline/posts/list/38732.html#237253 |
|
Thấy vui mỗi lần nhận ra mình có thể viết lại sản phẩm trong quá khứ hiệu quả và gọn gàng hơn 1 nửa |
|
Users currently in here |
1 Anonymous
|
|
Powered by JForum - Extended by HVAOnline
hvaonline.net | hvaforum.net | hvazone.net | hvanews.net | vnhacker.org
1999 - 2013 ©
v2012|0504|218|
|
|