[Sencha ExtJS 4] Xây dựng ứng dụng Flickr Search

Trong bài viết trước tôi đã trích dẫn một phần nhỏ của ứng dụng Flickr Search mà tôi đang viết demo. Từ loạt vbài này, tôi sẽ cố gắng trình giới thiệu từng bước để có thể xây dựng một ứng dụng Flickr Search tương đối hoàn chỉnh trên nền ExtJS 4.2 . Loạt bài viết này cũng không trình bày cách thức cài đặt môi trường làm việc với ExtJS, cũng như đi quá sâu vào việc trình bày xây dựng 1 ứng dụng MVC từ con số 0. Bạn cần phải nắm về MVC pattern, Javascript để có thể theo dõi loại bài này hoặc có thể để lại comment cho bất kỳ mục nào mà bạn không hiểu hoặc chưa rõ. Nhiều bạn từng hỏi tôi về IDE /application server ?  Tôi đang sử dụng WebStorm 5.0 để coding và NodeJS để deploy ứng dụng của mình. Bạn có thể tải trước mã nguồn của ứng dụng tại đây.

 

Ứng dụng này sẽ gồm những gì ?

Màn hình login – hiện tại nó không có tác dụng gì ngoài minh họa cho việc quản lý nhiều màn hình khác nhau.

login

Màn hình PhotoSearch – màn hình này sẽ bao gồm 1 toolbar, bạn sẽ gõ từ khóa tìm kiếm ở đây

search

Ngoài ra, khi bạn click lên hình thumbnail, một cửa sổ popup hiện ra cho phép bạn xem hình ở kích thước lớn hơn

popup

Bạn cần xây dựng những lớp nào ?

Trước hết, hãy xem qua screenshot project workspace của tôi

project

 Hãy chia ứng dụng của bạn ra các package tương ứng với M – Model , V – View , C – Controller. Dễ dàng thấy 3 màn hình mà tôi trình bày ở trên nằm lần lượt trong package view.  Trong project này tôi cũng sử dụng unit testing với Jasmine 1.3.1, tuy nhiên tôi không có ý định xây dựng ứng dụng này theo phương pháp TDD. TDD với ExtJS sẽ được trình bày trong một bài viết khác cùng với kỹ thuật Automation. Bạn có thể tham khảo file app-test.js, các file trong package specs cũng như chạy thử run-test.html.

Khởi tạo ứng dụng – app.js

Ext.Loader.setConfig({enabled:true});
Ext.application({
     requires: ['Ext.container.Viewport'],
     name: 'FlickrSearch',
     appFolder: 'app',
     controllers: ['ScreensController'],
     launch: function() {
         var viewport = Ext.create('Ext.container.Viewport', {
         layout: 'card',
         items: [
               {
                 xtype: 'authentication'
               },
               {
                 xtype: 'photosearch'
               }
         ]
      });
    this.on({
           signin: function() {
                 viewport.getLayout().setActiveItem(1);
          },
          signout: function() {
                viewport.getLayout().setActiveItem(0);
          }
    });
   }
});

Bạn cần quan tâm đến layout: ‘card’ – layout này có thể quản lý nhiều view (hoặc component)  – các view hoặc component sẽ có kích thước fit với ViewPort và tại mỗi thời điểm chỉ có 1 view hoặc component được hiển thị. Để chuyển qua view khác, gọi setActiveItem và truyền vào index thích hợp. Ứng dụng hiện tại có 2 view – authentication (index = 0) và photosearch (index = 1)

signin signout là 2 sự kiện được gửi từ ScreensController, application bằt 2 sự kiện này để thực hiện việc chuyển đổi giữa các màn hình

ScreensController

Controller này hoạt động theo đúng như tên của nó – handle hầu hết các action giữa các màn hình. Nếu bạn nhìn vào các code của các View, bạn sẽ không thấy các phần logic, truy cập store …ScreensController đã làm việc này. Theo quan điểm của tôi, view thuần túy chỉ định nghĩa phần giao diện, phần logic của nó nên chuyển sang cho controller hoặc model.

Tất cả các view do ScreensController quản lý cần được khai báo trong mảng views

 

 views:['AuthenticationView', 'PhotoSearchView', 'PhotoView'],

ScreensController giữ tham chiếu đến các view thông qua khai báo các tham chiếu đến từng view trong mảng refs

refs: [
        { ref: 'authentication', selector: 'authentication'},
        { ref: 'photosearch', selector: 'photosearch'}
 ],

Sau khi khai báo, ExtJS sẽ tự sinh ra getter cho view tương ứng – getter dựa trên selector với ký tự đầu tiên được viết hoa cùng với từ khóa get được thêm vào ở phía trước . Ví dụ, để tham chiếu đến photosearch, ta sẽ gọi

view = this.getPhotosearch();

từ đây, bạn có thể truy cập đến các hàm, biến được định nghĩa trong photosearch

Ở trên, tôi có trình bày trong app của chúng ta đang handle 2 sự kiện là sigin và signout. 2 sự kiện này được khởi động trong controller, thực tế thì đến từ 2 handler của các action trong các view do ScreensController quản lý

 signinHandler: function() {
    this.application.fireEvent("signin");
 },
 signoutHandler: function() {
    this.application.fireEvent("signout");
 },

PhotoModel và PhotoStore

Tham khảo đến bài viết trước để có cái nhìn tổng quan hơn về 2 class này

 

PhotoSearchView

Chú ý đến XTemplate được sử dụng trong view này. Tôi đã mất 1 tiếng để debug khi không thể render được các item từ XTemplate vì chưa khai báo itemSelector ( itemSelector: ‘div.thumb-wrap’, ). Với các phiên bản cũ của ExtJS thì itemSelector không bắt buộc (hoặc không có ?) nhưng với ExtJS 4.2 thì đây là thuộc tính bắt buộc. Tốt nhất khi sử dụng 1 component, class của ExtJS, bạn nên tham khảo document – mục config để xem các trường nào là bắt buộc.

Một số điểm cần chú ý

  • các view được khai báo trong controller sẽ được khởi tạo sẵn. Tôi bẫy sự kiện active của photosearch để xóa các kết quả search cũ khi màn hình này được active
  • alias được dùng để truy cập view từ controller
  • Ext.widget sẽ tạo ra instance mới – đừng hiểu nhầm đó là cách tham chiếu đến view.

 

Kết luận

ExtJS là một framework rất tốt để xây dựng các ứng dụng Rich Internet, đồng thời cũng là đối thủ nguy hiểm của Flex. Nếu bạn theo dõi blog của tôi từ trước, bạn có thể dễ dàng thấy tôi đang sử dụng ExtJS để thay thế Flex🙂

 

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s