Dojo từ dưới lên, Phần 1: Bắt đầu phát triển với Dojo

Bộ công cụ Dojo cho phép các nhà phát triển ứng dụng web tạo các ứng dụng Internet phong phú bằng cách cung cấp một loạt các tính năng để tiết kiệm thời gian và nỗ lực phát triển. Từ các trình trợ giúp DOM và JavaScript và XML không đồng bộ (Ajax) đến một thư viện tiện ích đang phát triển mạnh và các tính năng hướng đối tượng, Dojo bao gồm hầu như tất cả mọi thứ bạn cần để xây dựng các ứng dụng web có trang bị Ajax trên quy mô lớn. Nếu các hàm bạn đang tìm kiếm không có trong chính Dojo, thì có khả năng bạn có thể tìm thấy chúng trong DojoX, một kho lưu trữ các phần mở rộng và các tính năng thử nghiệm không có trong các mô đun Cơ bản hoặc Lõi của bộ công cụ này. Trong loạt bài này, hãy tìm hiểu cách phát triển các ứng dụng có trang bị Dojo từ dưới lên, bao gồm những điều cơ bản, tính năng hướng đối tượng to lớn của Dojo, và thư viện giao diện người dùng Dijit. Đến cuối loạt bài này, bạn sẽ được chuẩn bị tốt để phát triển các ứng dụng Dojo cho riêng mình.

Joe Lennon, Nhà phát triển phần mềm, Core International

Joe Lennon là một nhà phát triển phần mềm 24 tuổi đến từ Cork, Ireland. Joe là tác giả của cuốn sách Beginning CouchDB, (Khởi đầu với CouchDB) do Apress sắp xuất bản, và đã đóng góp một số bài viết và hướng dẫn kỹ thuật cho developerWorks IBM. Trong lúc rảnh rỗi, Joe thích chơi bóng đá (soccer), lang thang với các tiện ích, và làm việc trên gamerscore Xbox 360 của mình. Có thể liên hệ với ông qua trang Web của ông tại địa chỉ www.joelennon.ie



01 02 2012

Giới thiệu Bộ công cụ Dojo

Dojo đã được tạo ra vào năm 2004 để giúp cho quá trình phát triển các ứng dụng web DHTML và JavaScript dễ dàng hơn, ẩn giấu nhiều mâu thuẫn giữa các trình duyệt thường thấy trong các trình duyệt web hiện đại. Điều này cho phép đặt trọng tâm vào việc thực hiện các hàm chứ không phải tinh chỉnh mã để cho nó làm việc trên mọi trình duyệt. Dojo thuộc sở hữu của quỹ Dojo, được thành lập năm 2005 bởi Alex Russell và Dylan Schiemann. Dojo là phần mềm mã nguồn mở (OSS) và được phát hành theo giấy phép-kép (bạn có thể chọn một giấy phép nào bạn muốn tuân thủ) với cả hai Giấy phép miễn phí có tính học thuật (AFL) và giấy phép BSD có sửa đổi có sẵn.

Lướt qua các tính năng

Các tính năng của Bộ công cụ Dojo được phổ biến theo bốn gói riêng biệt. Sự phân chia này cho phép các nhà phát triển giữ kích thước tệp thư viện ở mức tối thiểu, đảm bảo hiệu năng của ứng dụng của họ không phải chịu gánh nặng do việc tải về thư viện JavaScript nặng nề. Ví dụ, nếu bạn chỉ cần Ajax hỗ trợ các hàm, bạn chỉ cần tính đến gói Base (Cơ sở); sẽ không có các thành phần giao diện người dùng Dijit mở rộng. Bạn sẽ tìm hiểu thêm về cách Dojo tải các mô đun khác nhau sau trong loạt bài này.

Gói Cơ sở
Gói phần mềm Cơ sở (Base) cung cấp nền tảng của bộ công cụ Dojo, bao gồm cả hàm ví dụ như các hàm tiện ích DOM, các tính năng truy vấn DOM dựa trên-bộ chọn CSS3, xử lý sự kiện, Ajax, hình ảnh động cơ bản và các tính năng hướng đối tượng dựa trên-lớp của Dojo. Phần lớn bài này tập trung vào gói Cơ sở.
Gói Lõi
Gói phần mềm Lõi (Core) bao gồm một số hàm bổ sung không có trong gói Cơ sở. Nói chung, các tính năng này có xu hướng không được sử dụng quá nhiều như là các hàm do gói Cơ sở cung cấp; do đó, chúng được nạp một cách riêng rẽ để giảm bớt gánh nặng lên gói Cơ sở. Theo cách đó, gói phần mềm Core cung cấp một số thành phần thực sự có ích bao gồm hình ảnh động, kéo và thả, I/O, quản lý dữ liệu, quốc tế hóa (i8n) và quản lý lịch sử trình duyệt nâng cao. Gói phần mềm Core không được trình bày trong bài này.
Gói Dijit
Gói phần mềm Dijit bao gồm thư viện giao diện người dùng mở rộng của Dojo về các tiện ích (widget) và các thành phần. Một số ví dụ về các tiện ích bao gồm các hộp thoại, các lịch biểu, các bảng màu, các chú giải công cụ và các cây. Nó cũng bao gồm một tập các nút điều khiển biểu mẫu cung cấp nhiều chức năng hơn so với các nút điều khiển biểu mẫu HTML tiêu chuẩn, cũng như các tùy chọn quản lý bố cục đầy đủ. Phần thứ ba của loạt bài này sẽ mô tả bao quát sâu hơn về gói Dijit.
Gói DojoX
Các phần mở rộng Dojo (DojoX) có chứa các dự án con khác nhau của bộ công cụ này. Hầu hết các tính năng thử nghiệm của Dojo nằm trong DojoX, nhưng nó còn chứa nhiều thành phần và các tính năng ổn định. DojoX sẽ được trình bày ngắn gọn trong phần thứ ba của loạt bài này.

Bắt đầu

Cũng nói đủ chuyện về Dojo rồi. Chúng ta hãy bắt đầu thực sự làm việc với bộ công cụ này. Phần này giải thích các cách sử dụng Dojo khác nhau trong các dự án của bạn, làm thế nào để thiết lập một môi trường phát triển khi sử dụng Firefox và trình cắm thêm Firebug, và cách viết một số mã Dojo để đảm bảo rằng tất cả mọi thứ đang làm việc như mong đợi.

Thiết lập Dojo

Cách dễ nhất để thiết lập Dojo là dùng nó từ một Mạng phân phối nội dung (CDN- Content Delivery Network), sẽ phân phối các tệp Dojo JavaScript từ một máy chủ gần khách truy cập chứ không phải từ máy chủ riêng của bạn. Không chỉ làm việc này để giúp tăng tốc độ tải kịch bản lệnh, mà việc này còn có nghĩa là có một cơ hội tăng thêm cho người dùng đã tải các tệp Dojo từ một trang web khác rồi, sẽ dẫn đến tải thiết lập Dojo từ bộ nhớ truy cập nhanh (cache), làm tăng nhanh việc thiết lập này lên hơn nữa.

Trong loạt bài này, giả sử rằng bạn đang sử dụng Dojo 1.5, mặc dù bất kỳ phiên bản 1.x nào cũng sẽ tương thích. Việc gộp thẻ <script> sau trong trang HTML của bạn sẽ tải Dojo 1.5 từ CDN của Google:

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"></script>

Ngoài ra, bạn có thể tải Dojo về máy chủ riêng của bạn và tải nó từ đó. Phương pháp ưa thích của tôi là tải từ một CDN, nhưng để có một bản dự phòng cục bộ cần một bước nào đó thực hiện sai trên máy chủ CDN. Để làm điều này, tải về Dojo và đặt các tệp vào một chỗ thích hợp có liên quan đến nơi bạn sẽ lưu trữ nội dung web của bạn. Giả sử đường dẫn có liên quan từ nội dung trang web của bạn đến các tệp kịch bản lệnh Dojo là "script/", đoạn mã trong Liệt kê 1 sẽ thử tải Dojo CDN đầu tiên, và nếu không thành công, nó sẽ tải phiên bản cục bộ để thay thế.

Liệt kê 1. Tải Dojo từ CDN có bản dự phòng cục bộ
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js">
</script>
<script>
typeof(dojo) === "undefined" && document.write(unescape('%3Cscript
src="js/libs/dojo-1.5.min.js"%3E%3C/script%3E'))
</script>

Điều quan trọng là tất cả mã bắt đầu bằng typeof(dojo) được đặt trên một dòng duy nhất; nếu không, nó sẽ không làm việc. Nếu bạn muốn kiểm tra bản dự phòng đang làm việc, chỉ cần ghi chú dòng tải từ CDN và thử nghiệm trang của bạn với ví dụ "Hello, World!" (Chào thế giới!) mà bạn sẽ tạo sau đây.

Sử dụng giao diện điều khiển Firebug

Thay vì cần tạo ra một trang web để thử Dojo, nhiều ví dụ trong bài này được thực hiện bằng cách sử dụng một trình cắm thêm Firefox tuyệt vời, đó là Firebug. Firebug cung cấp cho các nhà phát triển JavaScript đầy đủ các phương tiện ghi nhật ký, gỡ lỗi và và theo dõi mạng của giao diện điều khiển, làm cho quá trình thử nghiệm và sửa lỗi trong các ứng dụng JavaScript dễ dàng hơn nhiều. Một số trình duyệt web khác thực sự có các tính năng này, nhưng trong ví dụ này tôi sử dụng Firefox và Firebug do chúng đang có sẵn trên nhiều nền tảng.

Đầu tiên, bạn phải cài đặt Firefox và Firebug (xem Tài nguyên để biết thông tin tải về). Sau khi cài đặt Firefox, khởi động nó rồi tải về và cài đặt trình cắm thêm Firebug. Với Firebug đã cài đặt, bạn sẽ thấy một biểu tượng lỗi như hiển thị trên Hình 1 ở góc phải bên dưới cửa sổ Firefox của bạn. Việc nhấn vào biểu tượng này sẽ mở cửa sổ Firebug.

Hình 1. Biểu tượng và cửa sổ Firebug
Cửa sổ Firebug có biểu tượng lỗi ở góc phải bên dưới cửa sổ.

Để sử dụng giao diện điều khiển Firebug, nhấn vào thẻ Console (Giao diện điều khiển). Bạn có thể cần chạy giao diện điều khiển đầu tiên này bằng cách nhấn vào mũi tên xuống trong thẻ đó và nhấn Enable. Bây giờ, trong cửa sổ giao diện điều khiển, nhập mã sau đây: console.log("Test");.

Bạn sẽ thấy một kết quả như trong Hình 2, với một thông báo rằng trình gỡ lỗi JavaScript đang chạy để hỗ trợ giao diện điều khiển này.

Hình 2. Sử dụng giao diện điều khiển Firebug
Cửa sổ có thông báo 'chạy trình gỡ lỗi javascript để hỗ trợ giao diện điều khiển.'

Hello, World!

Tiếp theo, chúng ta hãy chạy thử Dojo. Với ví dụ "Hello, World!", bạn sẽ sử dụng Dojo để đính kèm một hàm khi DOM đã hoàn thành tải dữ liệu (xem Liệt kê 2). Hàm này chỉ đơn giản là in một thông báo "Hello, World!" đến cuối trang. Được rồi, do điều này sẽ không thay đổi chính xác cách bạn tạo các ứng dụng web, nên những gì nó sẽ làm là cho phép bạn chắc rằng Dojo có sẵn trên trang của bạn. Bạn cũng sẽ tải trang này trong suốt bài này để khám phá các tính năng Dojo khi sử dụng giao diện điều khiển Firebug.

Liệt kê 2. listing1.html: ứng dụng Hello World của Dojo
<html>
<head>
    <title>Exploring Dojo</title>
</head>
<body>
<h1>Exploring Dojo</h1>
<div id="message">This is a DIV element with id attribute message.</div>
<ul id="list">
    <li>This is the first item in a list</li>
    <li class="highlight">This is the second item in a list</li>
    <li>This is the third item in a list</li>
</ul>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js">
</script>
<script>
dojo.addOnLoad(function() {
    dojo.create(
        "div",
        {
            "innerHTML": "Hello, World!"
        },
        dojo.body()
    );
});
</script>
</body>
</html>

Kịch bản lệnh này sẽ đính kèm một hàm anonymous (ẩn danh) bắt đầu chạy khi DOM đã tải xong. Hàm này sử dụng dojo.create để xây dựng một phần tử <div> mới của DOM, thiết lập đặc tính innerHTML của nó cho "Hello, World!", và chèn nó vào phần thân của trang bằng cách sử dụng hàm tiện ích dojo.body. Kết quả này được thể hiện trong Hình 3. Bạn sẽ nhận thấy rằng thông báo "Hello, World!" đã được gắn thêm vào cuối phần thân của trang.

Hình 3. Trang "Hello, World!" với vẻ đẹp toàn diện của nó
Trang Hello World có văn bản và thông báo 'Hello World!' ở cuối văn bản.

Lúc này đừng xóa trang này hoặc đóng nó. Trong phần tiếp theo, bạn sẽ vẫn sử dụng trang này với mục đích duy nhất để tải Dojo, và bạn sẽ thử một số khía cạnh của Dojo trực tiếp bằng cách sử dụng giao diện điều khiển Firebug.

Trước khi chuyển sang phần tiếp theo, điều quan trọng là chỉ ra một cái gì đó về vị trí của các JavaScript trên trang này. Bạn có thể nhận thấy rằng thay vì có cả Dojo và JavaScript của trang trong phần <head> của tài liệu HTML, tôi đã thêm nó vào cuối trang, ngay trước phần tử <body> đóng. Lý do là khi đặt JavaScript ở đó, nó sẽ không chặn các phần tử khác của trang từ lúc tải. Khi sử dụng các thư viện JavaScript trong trang của bạn, điều quan trọng là bảo đảm rằng chúng không chặn các phần khác của trang của bạn từ lúc tải vì thế tối ưu hóa hiệu năng của trang của bạn. Để biết thêm thông tin về điều này, xem Tài nguyên.


Các điều cơ bản

Trong phần này, bạn sẽ tìm hiểu một số các hàm có ích mà Dojo cung cấp để giúp làm việc với DOM và các mảng dễ dàng hơn. Để thử các ví dụ trong phần này, giữ cho trang mà bạn tạo ra trong phần trước mở trong Firefox và gõ mã được đưa ra vào cửa sổ giao diện điều khiển Firebug.

Các hàm tiện ích DOM

Các hàm tiện ích DOM giúp làm việc với các phần tử trong DOM dễ dàng hơn bằng cách cung cấp khả năng tìm các mục theo ID của chúng hoặc sử dụng các bộ chọn CSS3. Ngoài ra còn có các hàm để tạo và hủy bỏ các phần tử cũng như để xử lý các nội dung của các phần tử hiện có.

dojo.byId

Hàm dojo.byId cho phép bạn chọn một nút DOM theo thuộc tính id của nó. Hàm này có một bí danh theo hàm JavaScript chuẩn document.getElementById nhưng rõ ràng viết ngắn hơn và cũng quan tâm đến một số mâu thuẫn giữa các trình duyệt. Bây giờ hãy sử dụng giao diện điều khiển Firebug để đăng nhập vào các nội dung của phần tử DOM có ID là "message": dojo.byId("message").innerHTML;.

Ở phía bên trái của giao diện điều khiển, bạn sẽ thấy đáp ứng được hiển thị trong Liệt kê 3.

Liệt kê 3. Đáp ứng
>>> dojo.byId("message").innerHTML;
"This is a DIV element with id attribute message1."

Dòng đầu tiên trong Liệt kê 3 chỉ đơn giản lặp lại lệnh đã được ban hành. Dòng thứ hai là kết quả của lệnh đó, trong trường hợp này, nội dung của phần tử <h1> có ID là "message".

Trước khi đi tiếp, chúng ta hãy làm vài thứ thú vị hơn một chút. Trong vùng trình soạn thảo của giao diện điều khiển, nhập lệnh được hiển thị trong Liệt kê 4.

Liệt kê 4. Lệnh dojo.fadeOut
dojo.fadeOut({
    node: dojo.byId("message"),
    duration: 600
}).play();

Bạn sẽ thấy phần tử mờ dần và biến mất khỏi trang. Để nó rõ dần trở lại, thay đổi giá trị tham khảo fadeOut trong dòng lệnh thành fadeIn và chạy lại nó. Khá tài tình? Việc này cho thấy cách bạn có thể thao tác động trang hiện tại bằng cách sử dụng giao diện điều khiển Firebug. Tất nhiên, những thay đổi này chỉ áp dụng cho việc tải trang hiện tại và sẽ không được tồn tại lâu bền nếu bạn chuyển hướng ra xa khỏi trang hoặc làm mới nó.

dojo.query

Trong phần trước, bạn đã học cách nhận được một giá trị tham khảo cho một phần tử DOM bằng cách sử dụng thuộc tính id của nó. Bình thường, sẽ không khả thi để thêm thuộc tính này cho mọi phần tử mà bạn muốn tương tác. Ngoài ra, một id phải là duy nhất. Vậy điều gì sẽ xảy ra nếu bạn muốn tham khảo một số phần tử cùng một lúc? Đây là nơi mà hàm dojo.query can thiệp.

Giả sử bạn muốn lấy một giá trị tham khảo cho tất cả các phần tử con <li> của danh sách không theo thứ tự có ID là "list" trong trang của bạn và in ra các nội dung của từng phần tử này tới giao diện điều khiển. Nhờ hàm dojo.query, điều này thực sự đơn giản (xem Liệt kê 5).

Liệt kê 5. Lệnh dojo.query
dojo.query("#list li").forEach(function(item) {
    console.log(item.innerHTML);
});

Lệnh này sẽ tạo kết quả đầu ra như trong Liệt kê 6 trong giao diện điều khiển.

Liệt kê 6. Kết quả đầu ra trong giao diện điều khiển
>>> dojo.query("#list li").forEach(function(item) { console.log
                                                       (item.innerHTML); });
This is the first item in a list
This is the second item in a list
This is the third item in a list
[li, li.highlight, li]

Hàm dojo.query chấp nhận một đối số chuỗi với một giá trị tham khảo của bộ chọn CSS3 cho các phần tử mà bạn muốn chọn. Trong trường hợp cụ thể này, bạn sẽ nói rằng bạn muốn chọn tất cả các phần tử li là phần tử con của phần tử có ID "list". Hàm này trả về một mảng các phần tử phù hợp với truy vấn. Trong ví dụ ở Liệt kê 6, bạn sử dụng hàm dojo.forEach để lặp lại hết mảng này và ghi nhật ký đặc tính innerHTML của mỗi phần tử được tìm thấy vào giao diện điều khiển. Bạn sẽ tìm hiểu thêm về hàm này và các hàm mảng khác trong phần tiếp theo.

Trước khi di chuyển lên, chúng ta hãy sử dụng dojo.query để tìm bất kỳ phần tử HTML nào có tên lớp là highlight và áp dụng một số kiểu dáng để làm cho chúng nổi bật (xem Liệt kê 7).

Liệt kê 7. Sử dụng dojo.query để tìm bất kỳ phần tử HTML nào có tên lớp là highlight
dojo.query(".highlight").style({
    backgroundColor: "yellow",
    color: "red"
});

Bạn sẽ nhận thấy rằng mục thứ hai trong danh sách không theo thứ tự trên trang thay đổi sang có một nền màu vàng, với màu văn bản thay đổi thành màu đỏ. Bạn có thể nhận thấy rằng trong trường hợp này hàm dojo.forEach đã không được sử dụng. Tôi sẽ trình bày lý do tại sao hàm này không cần thiết trong phần tiếp theo, "Các mảng và các NodeList."

Các hàm tiện ích có ích khác

Ngoài truy vấn DOM và chọn phần tử, có một số hàm tiện ích khác có sẵn trong Dojo giúp làm việc với DOM dễ dàng hơn nhiều. Bạn đã nhìn thấy một vài hàm trong số này trong ví dụ "Hello, World". Hàm dojo.body chỉ đơn giản trả về một giá trị tham khảo cho phần tử <body> của tài liệu, dojo.body, và trả về chính đối tượng tài liệu đó. dojo.create cho phép bạn nhanh chóng tạo ra một phần tử mới, định nghĩa thuộc tính của nó, và đặt nó trong DOM.

Các hàm khác hiện có bao gồm dojo.place, cho phép bạn đặt các phần tử hiện tại hoặc mới vào bất cứ nơi nào trong tài liệu. dojo.empty chính là điều mà bạn mong muốn ở nó — nó xóa rỗng nội dung của một phần tử DOM. dojo.destroy loại bỏ một nút, mang theo bất kỳ phần tử con nào cùng với nó. Để biết thêm thông tin về bất kỳ các hàm này, xem Tài nguyên để có được một liên kết đến tài liệu tham chiếu Dojo.

Các mảng và các NodeList

Các mảng cho phép bạn lưu trữ một bộ sưu tập các giá trị và chúng có sẵn trong tiêu chuẩn JavaScript. Trong Dojo, các mảng được mở rộng để bao gồm một số hàm trợ giúp. Các mảng mở rộng được gọi là các NodeList. Một NodeList có thể sử dụng bất kỳ hàm mảng tiêu chuẩn nào cũng như các hàm Dojo cụ thể bổ sung. Khi bạn sử dụng hàm dojo.query được mô tả ở phần trước, giá trị trả về là một đối tượng NodeList (hoặc dojo.NodeList riêng biệt). Chúng ta hãy xem một số hàm có sẵn trong các NodeList.

dojo.forEach

Hàm đầu tiên đáng thảo luận là hàm dojo.forEach mà bạn đã thấy trong ví dụ dojo.query từ phần trước của bài này. Hàm này cho phép bạn định nghĩa một trình lặp (iterator) trên một NodeList, cung cấp một hàm sẽ được áp dụng cho từng mục trong NodeList. Chúng ta hãy xem một ví dụ cơ bản trong Liệt kê 8.

Liệt kê 8. Ví dụ cơ bản
var list = ['My','name','is','Joe'];
dojo.forEach(list, function(item, i) {
    console.log((i+1)+'. '+item);
});

Mã trong Liệt kê 8 này sẽ cho kết quả đầu ra được hiển thị trong Liệt kê 9.

Liệt kê 9. Đầu ra
>>> var list = ['My','name','is','Joe']; dojo.forEac...item, i) 
                             { console.log((i+1)+'. '+item); });
1. My
2. name
3. is
4. Joe

Như bạn có thể thấy, hàm forEach lấy từng mục trong mảng và thực hiện hàm gắn kèm trên nó. Ở trên, bạn đã sử dụng một hàm anonymous (ẩn danh), nhưng bạn cũng có thể sử dụng một hàm có tên, như trong Liệt kê 10.

Liệt kê 10. Lặp lại hết một mảng với dojo.forEach bằng cách sử dụng một hàm có tên
var list = ['My','name','is','Joe'];

var printArray = function(item, i) {
    console.log((i+1)+'. '+item);
}

dojo.forEach(list, printArray);

dojo.indexOf

Hàm dojo.indexOf cho phép bạn tìm thấy vị trí có một giá trị cụ thể trong một mảng. Cách tốt nhất để minh họa nó là dùng ví dụ. Sử dụng mảng danh sách được tạo ra trong phần trước, thử tính toán chỉ mục của mảng có giá trị name ở trong: dojo.indexOf(list, "name");.

Hàm này trả về kết quả được hiển thị trong Liệt kê 11.

Liệt kê 11. Kết quả
>>> dojo.indexOf(list, "name");
1

Do đó giá trị name có chỉ mục là 1 trong mảng này. Hãy nhớ rằng các mảng JavaScript bắt đầu từ chỉ mục là 0, nên giá trị này là mục thứ hai trong mảng. Nếu bạn cố gắng sử dụng hàm này khi cung cấp một giá trị không còn trong mảng nữa, giá trị trả về là -1.

Hàm này trả về chỉ mục đầu tiên được tìm thấy với giá trị đã cho, vì vậy nếu có nhiều mục trong mảng có cùng một giá trị, hàm này sẽ dừng lại ở mục đầu tiên. Dojo cung cấp một hàm tương tự, dojo.lastIndexOf, cho phép bạn tìm chỉ mục cuối cùng của một giá trị cụ thể. Hàm này hoạt động theo cách chính xác tương tự như dojo.indexOf.

dojo.filter

Hàm dojo.filter cho phép bạn tạo một mảng mới là một phiên bản được lọc của mảng khác. Ví dụ, nếu bạn muốn tạo một phiên bản mới của mảng danh sách mà bạn tạo ra trước đó, nhưng loại trừ bất kỳ các mục có giá trị is, bạn có thể sử dụng đoạn mã được hiển thị trong Liệt kê 12.

Liệt kê 12. Lọc một mảng để tạo ra một mảng mới
var filteredList = dojo.filter(list, function(item) {
    return item != "is";
});

dojo.forEach(filteredList, "console.log(item)");

This results in the following output:

>>> var filteredList = dojo.filter(list, 
function(it...dojo.forEach(filteredList, "console.log(item)");
My
name
Joe

Các hàm NodeList khác

Dojo có chứa một vài hàm NodeList khác rất có ích khi làm việc với các mảng. Hàm dojo.map cho phép bạn tạo ra một mảng mới là một phiên bản sửa đổi của một mảng hiện có. Ví dụ, bạn có thể có một mảng các số biểu thị các giá trị tiền tệ. Bạn có thể sử dụng một hàm ánh xạ để trả về một mảng các giá trị này theo một định dạng tiền tệ. dojo.some cho phép bạn kiểm tra xem ít nhất một mục trong một mảng có phù hợp với tiêu chuẩn đã quy định không. Tương tự, dojo.every được sử dụng để kiểm tra xem tất cả các mục trong một mảng có phù hợp với tiêu chuẩn quy định không. Để có một danh sách đầy đủ các hàm NodeList và tài liệu liên kết của chúng, xem Tài nguyên.


Xử lý sự kiện trong Dojo

Hầu hết các thư viện JavaScript có một công cụ xử lý sự kiện JavaScript nguyên gốc giữa các trình duyệt, cho phép bạn đính kèm các hàm được gọi khi một sự kiện DOM được kích hoạt. Rất tiện lợi, Dojo mang khái niệm này tiến một bước xa hơn bằng cách cho phép bạn kết nối các hàm với các hàm khác, có thể là các sự kiện DOM, các sự kiện đối tượng, các hàm do người dùng định nghĩa, hoặc "các chủ đề," được thảo luận sau trong phần này.

Xử lý sự kiện DOM

Cách đầu tiên gắn các hàm với các sự kiện DOM là sử dụng hàm dojo.connect. Cách tốt nhất để minh họa điều này là dùng ví dụ. Trong giao diện điều khiển Firebug, nhập mã trong Liệt kê 13.

Liệt kê 13. Gắn các hàm với các sự kiện DOM khi sử dụng dojo.connect
var message = dojo.byId("message");
dojo.connect(message, "onclick", function() {
    alert(message.innerHTML);
});

Điều này dẫn đến kết quả đầu ra như ở Liệt kê 14 trong giao diện điều khiển.

Liệt kê 14. Đầu ra
>>> var message = dojo.byId("message"); dojo.connect..., function() 
                                              { alert(message.innerHTML); });
[div#message, "onclick", function(), 1]

Điều đó là tuyệt vời và tất cả, những không phải hàm này thực sự làm một cái gì đó chứ? Chắc chắn rồi. Dojo đã kèm theo một hàm cho trình xử lý sự kiện click của phần tử có ID "message". Để thử nghiệm nó, hãy nhấn vào thông báo trên màn hình với nội dung "This is a DIV element with id attribute message" (Đây là một phần tử DIV có thông báo thuộc tính id). Bạn sẽ thấy một hộp cảnh báo JavaScript, như thể hiện trong Hình 4.

Hình 4. Gắn các hàm cho các sự kiện DOM
Một hộp thông báo có dòng 'Đây là một phần tử DIV với thông báo thuộc tính id.'

Đẹp và dễ dàng, có phải không? Điều gì sẽ xảy ra nếu bạn muốn đính kèm một sự kiện cho tất cả các mục trong một mảng? Ví dụ, chúng ta nói bạn muốn mỗi mục trong danh sách không theo thứ tự trên trang của bạn làm nổi bật bằng in đậm khi bạn nhấn vào chúng. Bạn có thể dễ dàng làm điều này với mã trong Liệt kê 15.

Liệt kê 15. Gắn các sự kiện vào một mảng các phần tử
dojo.query("#list li").forEach(function(item) {
    dojo.connect(item, "onclick", function() {
        dojo.style(item, {
            fontWeight: "bold"
        });
    });
});

Hãy thử nó, nó hoạt động. Dojo cho phép bạn viết đoạn mã này theo cách còn ngắn gọn hơn. Thay vì sử dụng forEach để lặp qua mảng, để thay thế bạn có thể sử dụng một hàm phím tắt NodeList.connect để làm điều đó, như trong Liệt kê 16.

Liệt kê 16. Gắn các sự kiện vào một mảng các phần tử (được cải thiện)
dojo.query("#list li").onclick(function(e) {
    dojo.style(e.target, {
        fontWeight: "bold"
    });
});

Bởi vì bạn đã gắn một sự kiện vào danh sách rồi, bạn nên làm mới trang trước khi thử mã trong Liệt kê 16 để đảm bảo nó sẽ hoạt động. Đối số e là một giá trị tham khảo cho đối tượng Event (sự kiện), và đặc tính target (mục tiêu) của đối tượng này để cho bạn nhận biết phần tử đã bắt đầu thực hiện sự kiện. Bạn sử dụng nó để nhận biết phần tử nên được áp dụng kiểu dáng in đậm. Hãy thử nhấn vào ba mục danh sách, mỗi mục trong đó sẽ trở thành in đậm sau khi bạn nhấn vào chúng.

Kết nối các hàm với các hàm khác

Trong các ví dụ trước, bạn đã kết nối các hàm với các sự kiện DOM. Dojo cũng cho phép bạn kết nối các hàm với các hàm khác theo cách tương tự. Một ví dụ về điều này có thể là một hàm cho thấy một hình ảnh bánh xe quay ở đâu đó trên trang của bạn. Khi người dùng thực hiện một hàm Ajax, bạn muốn hiển thị hình ảnh này. Cũng vậy, khi hàm này đã trả về một đáp ứng, bạn muốn ẩn đi hình ảnh này. Nếu không sử dụng dojo.connect, mã của bạn có thể trông như Liệt kê 17.

Liệt kê 17. Kết nối các hàm với các hàm khác mà không dùng dojo.connect
function toggleImage() {
    //Code to show/hide loading image goes here
}

function callAjax() {
    toggleImage();
    //Code to call Ajax function goes here
}

function handleResponse() {
    //Code to handle Ajax response goes here
    toggleImage();
}

Trong khi không có bất kỳ lỗi nào với mã này, cuộc gọi hàm toggleImage được ấn định trong cả hai hàm callAjaxhandleResponse. Nếu bạn muốn bổ sung thêm một cuộc gọi hàm khác, bạn sẽ phải thay đổi các hàm này một lần nữa để có các cuộc gọi thêm. Thay vào việc thêm cuộc gọi hàm tới chính các hàm này, bạn có thể sử dụng dojo.connect để thiết lập liên kết giữa chúng. Liệt kê 18 cho thấy phương thức dojo.connect có thể trông như thế nào.

Liệt kê 18. Kết nối các hàm với các hàm khác dùng dojo.connect
function toggleImage() {
    //Code to show/hide loading image goes here
}

function callAjax() {
    //Code to call Ajax function goes here
}

function handleResponse() {
    //Code to handle Ajax response goes here
}

dojo.connect(callAjax, toggleImage);
dojo.connect(handleResponse, toggleImage);

Kiểu dáng mã hóa này có thể không là hương vị của mỗi nhà phát triển, nhưng nó cho phép bạn tổ chức mã của bạn theo cách cho dễ đọc hơn nhiều.

Xuất bản và đăng ký các chủ đề

Khía cạnh cuối cùng về xử lý sự kiện Dojo đáng nói đến là khả năng xuất bản và đăng ký theo các chủ đề. Điều này cho phép các thành phần Dojo tương tác với nhau, ngay cả khi chúng không biết về sự tồn tại của nhau. Ví dụ, chúng ta nói rằng bạn đã định nghĩa một chủ đề có tên là printName, hy vọng một đối tượng message có tên và họ của cá nhân. Bạn có thể có một thành phần đăng ký theo chủ đề này, sẽ in tên vào giao diện điều khiển bất cứ lúc nào có một thành phần khác xuất bản theo chủ đề này có tên cá nhân. Liệt kê 19 cho thấy một ví dụ của một đăng ký như vậy (cứ tự nhiên thử nó trong Firebug).

Liệt kê 19. Đăng ký
dojo.subscribe("printName", function(msg) {
    console.log("The person's name is: "+msg.first_name+" "+msg.last_name);
});

Để xuất bản theo chủ đề này, bạn cần phải vượt qua một mảng các đối tượng tuân thủ các API của chủ đề (trong trường hợp này, các đối tượng phải có một tên và họ). Liệt kê 20 là một ví dụ.

Liệt kê 20. Xuất bản theo một chủ đề
dojo.publish("printName", [
    {
        first_name: "Joe",
        last_name: "Lennon"
    }
]);

Việc này tạo ra kết quả được hiển thị trong Liệt kê 21.

Liệt kê 21. Đầu ra
>>> dojo.publish("printName", [ { first_name: "Joe", last_name: "Lennon" } ]);
The person's name is: Joe Lennon

Như bạn có thể thấy, bằng việc xuất bản đối tượng này theo chủ đề printName, hàm đã đăng ký của bạn xuất ra một thông báo tương ứng với giao diện điều khiển.


Trao quyền cho Ajax bằng dojo.xhr*

Việc tạo các ứng dụng web có trang bị Ajax thường được thực hiện bằng cách tạo một đối tượng XmlHttpRequest (XHR) đối tượng này sẽ tạo ra một yêu cầu HTTP với một địa chỉ URL cụ thể, chuyển qua một tiêu đề và phần thân của yêu cầu, và định nghĩa các hàm gọi lại để xác định những gì nên được thực hiện khi đáp ứng trả về với một phần thân đáp ứng thành công hay một đáp ứng HTTP thất bại. Việc thực hiện các XHR giữa các trình duyệt có thể nói ít nhất là rất chán, nhưng, may mắn thay, Dojo làm dịu đáng kể nỗi đau đó bằng một tập các hàm dojo.xhr* cho phép bạn thực hiện các yêu cầu GET, POST, PUTDELETE.

Bốn hàm được cung cấp như sau:

  • xhrGet
  • xhrPost
  • xhrPut
  • xhrDelete

Tất cả các hàm này theo cú pháp như nhau: chấp nhận một đối tượng cấu hình đặc tính đơn lẻ làm một đối số. Trong đối tượng này, bạn có thể định nghĩa các khía cạnh khác nhau của yêu cầu Ajax mà bạn muốn thực hiện. Một lần nữa, các tùy chọn này đều giống nhau trên tất cả các hàm XHR.

Các tùy chọn cấu hình

Một số các tùy chọn cấu hình có ích có sẵn cho các hàm XHR như sau:

url
Đây là địa chỉ URL mà yêu cầu HTTP cần được thực hiện. Nó phải nằm trong cùng miền và cùng cách kết hợp cổng như trang đang thực hiện yêu cầu này.
handleAs
Cho phép bạn định nghĩa định dạng mà đáp ứng cần được xử lý. Mặc định là text, nhưng cũng có sẵn json, javascript, xml và một vài tùy chọn khác. Bạn sẽ thấy một ví dụ về tạo một yêu cầu Ajax với một hàm gọi lại để xử lý một định dạng đáp ứng JSON sau trong phần này.
form
Hoặc là một giá trị tham khảo đến hoặc biểu diễn chuỗi ID của một phần tử <form>. Các giá trị của từng trường theo biểu mẫu này sẽ được gửi đi cùng với yêu cầu như phần thân của yêu cầu.
content
Một đối tượng có chứa các tham số mà bạn muốn chuyển tài nguyên vào phần thân của yêu cầu. Đối tượng này sẽ được trộn lẫn với các giá trị được lấy từ đặc tính form nếu cả hai được cung cấp.

Một ví dụ về một hàm XHR được hiển thị trong Liệt kê 22.

Liệt kê 22. Ví dụ về một cuộc gọi hàm XHR
dojo.xhrGet({
    url: "save_data.php",
    content: {
        id: "100",
        first_name: "Joe",
        last_name: "Lennon"
    }
});

Hàm này sẽ tạo không đồng bộ một yêu cầu HTTP GET đến tệp save_data.php trong cùng một vị trí như chính tài liệu đó. Nó sẽ chuyển các đặc tính của đối tượng nội dung tới kịch bản lệnh PHP làm các tham số. Trong PHP, sau đó bạn sẽ sử dụng biến $_GET để lấy ra các giá trị này và có thể lưu chúng vào một cơ sở dữ liệu.

Các hàm gọi lại

Trong ví dụ trước, bạn đã học cách để bạn có thể gọi một yêu cầu Ajax bằng dojo.xhrGet. Trong khi ví dụ đã đủ để thực sự đưa ra yêu cầu, nó đã không cung cấp phương tiện nào để xử lý bất kỳ đáp ứng nào. Các hàm gọi lại cũng được truyền tới đối tượng cấu hình. Các tùy chọn sau đây có sẵn:

load
Hàm này sẽ được thực hiện khi một yêu cầu Ajax trả về một thông báo đáp ứng thành công. Các dữ liệu đáp ứng và đối tượng yêu cầu được chuyển tới hàm này làm các đối số.
error
Hàm này sẽ được thực hiện nếu có một vấn đề với yêu cầu Ajax. Hàm này có thể xảy ra nếu địa chỉ URL được chỉ rõ trong yêu cầu Ajax là không hợp lệ, nếu yêu cầu tạm dừng, hoặc nếu xảy ra một số lỗi HTTP khác. Thông báo lỗi và đối tượng yêu cầu được chuyển làm các đối số.
handle
Hàm này cho phép bạn kết hợp các hàm gọi lại tải và lỗi vào một hàm duy nhất (có ích nếu bạn thực sự không quan tâm xem này yêu cầu dẫn đến thành công hay lỗi không).

Trong ví dụ tiếp theo, bạn sẽ tạo ra một cuộc gọi Ajax với một hàm gọi lại tải, sẽ tải một số dữ liệu từ một tệp JSON và in nó lên trang này.

Làm việc với dữ liệu JSON

Hãy đặt các hàm dojo.xhr* vào một bài thử nghiệm tốt hơn bằng cách tạo ra một ví dụ thực tế hơn. Đầu tiên, tạo một tệp mới — đặt tệp này trong cùng thư mục như tệp listing1.html — và thêm một số dữ liệu JSON vào nó. Các nội dung của tệp được hiển thị trong Liệt kê 23.

Liệt kê 23. data.json — một yêu cầu Ajax xử lý dữ liệu JSON
{
    count: 4,
    people: [
        {
            first_name: "Joe",
            last_name: "Lennon",
            age: 25		
        },{
            first_name: "Darragh",
            last_name: "Duffy",
            age: 33
        },{
            first_name: "Jonathan",
            last_name: "Reardon",
            age: 30
        },{
            first_name: "Finian",
            last_name: "O'Connor",
            age: 23
        }
    ]
}

Bây giờ tạo một yêu cầu Ajax trong Firebug (chắc chắn rằng trang listing1.html được nạp vào Firefox để cho Dojo được tải). Yêu cầu này sử dụng hàm gọi lại load để xử lý đáp ứng JSON và in một bảng lên trang này (xem Liệt kê 24).

Liệt kê 24. Sử dụng Ajax để tải và xử lý dữ liệu JSON
dojo.xhrGet({
    url: "data.json",
    handleAs: "json",
    load: function(data) {
        var table = "<table border=\"1\">";
        table += "<tr><th>Name</th><th>Age</th>
</tr>";
        dojo.forEach(data.people, function(person) {
            table += "<tr><td>";
            table += person.first_name+" "+person.last_name;
            table += "</td><td>";
            table += person.age;
            table += "</td></tr>";
        });
        table += "</table>";
        dojo.place(table, dojo.body());
    }
});

Hãy thử mã được hiển thị trong Liệt kê 24 trong Firebug. Nên thêm động một bảng vào trang của bạn với dữ liệu được nạp từ tệp JSON. Việc này được thể hiện trong Hình 5.

Hình 5. Bảng có tải Ajax từ dữ liệu JSON
Bảng trên trang có 4 tên người và tuổi tương ứng của họ.

Trong một ví dụ thế giới thực, bạn sẽ sử dụng một ngôn ngữ phía máy chủ như PHP, Python, ASP.NET hoặc Java để tạo dữ liệu JSON động dựa trên các tham số được truyền cho nó bằng yêu cầu Ajax.


Kết luận

Trong phần này của loạt bài Dojo từ dưới lên, bạn đã tìm hiểu về Dojo và các điều cơ bản về cách sử dụng nó. Đặc biệt, bạn đã tìm hiểu về các hàm tiện ích DOM khác nhau, các hàm mảng, xử lý sự kiện và các tính năng XHR. Trong phần tiếp theo của loạt bài này, bạn sẽ tìm hiểu cách sử dụng các tính năng hướng đối tượng dựa vào lớp như-Java™ của Dojo.


Tải về

Mô tảTênKích thước
Article source codedojo.ground.1.zip1KB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Nguồn mở
ArticleID=790479
ArticleTitle=Dojo từ dưới lên, Phần 1: Bắt đầu phát triển với Dojo
publish-date=02012012