Tạo một javascript SPA framework đơn giản với phong cách chính mình
SPA – Single Page (Web) Application là một design pattern hướng đến việc đem lại trải nghiệm người dùng trên web giống như trên desktop bằng việc gói toàn bộ nội dung của website hay một web application chỉ trong một trang duy nhất.
Những ưu điểm của SPA đem lại:
- Đem lại trải nghiệm tốt cho người dùng qua hiệu năng, xử lý linh hoạt…
- Thân thiện với các trang web đòi hỏi tương tác cao của người dùng như chat, hệ thống nhập liệu…
- Bảo vệ tốt thông tin trước các web crawler.
Điểm yếu:
- Không thân thiện với các công cụ SEO, Analysis…
- Không thân thiện với các trang web cần sự màu mè.
- Việc xây dựng phát triển duy trì tốn công.
Việc lựa chọn SPA hay dạng Multi Page (Web) Application truyền thống phụ thuộc vào mục tiêu hướng đến của website. Tuy nhiên, có một thực tế là các trang lớn như facebook, google đều đã đi theo xu thế này.
Hiện nay, có rất nhiều framework hỗ trợ SPA như Angular, React, ExtJS… tuy nhiên, các framework này chủ yếu hỗ trợ mô hình MVC còn mô hình MVP thì hỗ trợ rất kém. Trong khi đó, các ứng dụng Enterprise lại đòi hỏi việc đóng gói các thành phần tạo thành các module để tái sử dụng hoặc tăng cường khả năng lắp ghép linh hoạt, là điểm vượt trội của MVP so với MVC (chi tiết về MV* vui lòng hỏi google).
Với nhu cầu cần áp dụng SPA với MVP như vậy, không có cách nào khác là tự xây dựng một framework riêng với các tiêu chí:
- SPA
- MVP
- AMD
- EDP
SPA và MVP đã đề cập, vậy còn AMD và EDP là gì?
AMD – Asynchronous Module Definition tạm dịch là đặc tả module không đồng bộ. Để hiểu về thuật ngữ này, quay lại lịch sử.
Vào thời kỳ đầu tiên, việc khai báo các javascript thường được tập trung trong thẻ <head> của trang HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
< head >
< meta http - equiv = "content-Type" content = "text/html;charset=UTF-8" / >
< link href = "stylesheets/default_style.css" rel = "stylesheet" type = "text/css" / >
< link href = "stylesheets/cupertino/jquery-ui-1.8.6.custom.css" rel = "stylesheet" type = "text/css" / >
<script type = "text/javascript" src = "js/jquery-1.4.2.min.js" > </script>
<script type = "text/javascript" src = "js/jquery-ui-1.8.6.custom.min.js" > </script>
<script type = "text/javascript" src = "js/JSON2.js" > </script>
<script type = "text/javascript" src = "js/ww.jquery.js" > </script>
<script type = "text/javascript" src = "js/jquery.metadata.js" > </script>
<script type = "text/javascript" src = "js/jquery.maskedinput-1.2.2.min.js" > </script>
<script type = "text/javascript" src = "js/pages/index.html.js" > </script>
< / head >
|
Do quá trình nạp được thực hiện tuần tự từ trên xuống dưới nên xảy ra nhu cầu cần nạp các javascript theo đúng dependency; như ví dụ trên: jquery-ui phụ thuộc vào jquery, ww.jquery phụ thuộc vào jquery và JSON2.
Một số framework chuyên xử lý vấn đề loading như LAB đã giải quyết được việc này:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<script type = "text/javascript" >
App = { } ;
App . Templates = [ ] ;
$ LAB
. script ( 'js/libs/json/json2.js' , 'js/libs/jquery/jquery-1.6.2.min.js' , 'js/libs/imageflow/imageflow.js' ) . wait ( function ( ) {
$ ( 'script.template' ) . each ( function ( ) {
App . Templates [ this . id ] = $ ( this ) . html ( ) ;
} ) ;
} )
. script ( 'js/libs/jquery/plugins/jquery-ui-1.8.16.custom.min.js' ) . wait ( )
. script ( 'js/libs/jquery/plugins/ww.jquery.js' , 'js/libs/jquery/widgets/window/jquery.window.min.js' , 'js/libs/jquery/widgets/upload/fileuploader.js' ) . wait ( )
. script ( 'js/libs/wrs/wrs.js' ) . wait ( )
. script ( 'js/app/dto.js' , 'js/app/model.js' , 'js/app/eventbus.js' ) . wait ( )
. script ( 'js/app/presenter.js' , 'js/app/proxy.js' ) . wait ( )
. script ( 'js/app/guest.js' ) ;
</script>
|
Tuy nhiên, vẫn còn tồn tại một vấn đề không nhỏ. Đó là việc nạp các javascript vẫn theo tuần tự, nạp xong script này mới bắt đầu tiếp tục nạp script khác tạo nên một độ trễ lớn trong quá trình khởi tạo trang. Để khắc phục nhược điểm đó, khái niệm asynchronous được đưa vào thi công các framework loading thế hệ sau để đảm bảo rằng các script không phụ thuộc với nhau có thể được nạp song song để tận dụng tối đa cơ chế đa luồng mà các trình duyệt mới hỗ trợ.
Xong chữ Asynchronous. Vậy còn module thì sao? Lập trình javascript truyền thống chủ yếu hướng đối tượng được thông qua cơ chế prototype
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
Notifier = function ( )
{
this . observers = [ ] ;
this . suppressNotifications = 0 ;
} ;
Notifier . prototype . addObserver = function ( observer )
{
if ( ! observer )
return ;
var len = this . observers . length ;
for ( var i = 0 ; i & amp ; lt ; len ; i ++ )
{
if ( this . observers [ i ] == observer )
return ;
}
this . observers [ len ] = observer ;
} ;
|
Cơ chế này làm tốt trên yếu tố kế thừa nhưng tính đóng gói kém. Do vậy, các nhà lập trình javascript đã sang tạo ra phong cách lập trình functional với cơ chế module giải quyết tốt hơn nhu cầu trên. Khi kết hợp cả hai, chúng giải quyết tốt cả kế thừa và đóng gói như đoạn code ví dụ dưới đây (chi tiết về module vui lòng cũng hỏi google) .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/*global document, window, alert, console, require, define*/
/*jslint nomen: true*/
( function ( ) {
'use strict' ;
if ( typeof define === 'function' & amp ; amp ; & amp ; amp ; define . amd ) {
define ( [ 'surfly/core/util' ] , function ( ) {
var Util = require ( 'surfly/core/util' ) ;
function BaseObject ( ) {
this . _sid = Util . randomSid ( 16 ) ;
}
BaseObject . prototype . getSid = function ( ) {
return this . _sid ;
} ;
return BaseObject ;
} ) ;
}
} ( ) ) ;
|
All in one, chúng ta có chuẩn Asynchronous Module Definition là chuẩn được xây dựng với mục tiêu quản lý dependency giữa các module và nạp chúng không đồng bộ theo ý muốn. Đây là chuẩn được thừa nhận rộng rãi, hỗ trợ bởi rất nhiều framework như jQuery, Dojo, NodeJS…
EDP – Event Driven Programing tạm dịch là Lập trình điều hướng sự kiện. Đây là một trong các yếu tố quan trọng để xử lý giao tiếp giữa các module, được sử dụng để làm giảm sự liên kết giữa các module. Lấy ví dụ:
1
2
3
4
5
6
7
|
A . doA = function ( ) {
B . doB1 ( ) ;
B . doB2 ( ) ;
C . doC1 ( ) ;
}
|
Cách viết như trên, có sự liên kết chặt giữa A với B và C, đây là một thiết kế không tốt. Cách viết hướng sự kiện thay thế như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
A . doA = function ( ) {
fireEvent (‘ RequestBC’ ) ;
}
B . listen = function ( Event event ) {
if ( event === Event (‘ RequestBC’ ) ) {
doB1 ( ) ;
doB2 ( ) ;
}
}
C . listen = function ( Event event ) {
if ( event === Event (‘ RequestBC’ ) ) {
doC1 ( ) ;
}
}
|
Sau khi thay thế, kết quả là ở mức độ logic, A, B, C hoàn toàn ko có sự liên kết, bởi vậy, việc nâng cấp, thay thế, lắp ghép các module trên có thể thực hiện dễ dàng hơn rất nhiều.
Kết thúc phần 1 ở đây.
Tác giả: Lê Đình Quang
- Tài liệu về hệ thông tin địa lý (GIS – Geographic Information System)
- Mô hình giao hàng kích thước lớn tại nhà
- Quản lý giao vận thông minh
- Điều hành hãng xe công nghệ, ứng dụng đặt xe trên smartphone tương tự Uber, Grab,...
- Lợi ích trong việc Vận Tải hàng hoá bằng container
- Làm thế nào để nâng cao hiệu quả của ngành Logistics
- Bảo hiểm hàng hóa chuyên chở bằng đường biển
- Quy trình thuê xe du lịch, bạn nên biết
- Danh sách website B2B phục vụ xuất nhập khẩu, logistics
- Lược đồ các phương thức vận tải, dạng bản đồ tư duy dễ hiểu và tổng hợp
- Phần mềm quản lý xe thường có những tính năng gì?
- Phân tích SWOT ngành logistics Việt Nam
DVMS chuyên:
- Tư vấn, xây dựng, chuyển giao công nghệ Blockchain, mạng xã hội,...
- Tư vấn ứng dụng cho smartphone và máy tính bảng, tư vấn ứng dụng vận tải thông minh, thực tế ảo, game mobile,...
- Tư vấn các hệ thống theo mô hình kinh tế chia sẻ như Uber, Grab, ứng dụng giúp việc,...
- Xây dựng các giải pháp quản lý vận tải, quản lý xe công vụ, quản lý xe doanh nghiệp, phần mềm và ứng dụng logistics, kho vận, vé xe điện tử,...
- Tư vấn và xây dựng mạng xã hội, tư vấn giải pháp CNTT cho doanh nghiệp, startup,...
Vì sao chọn DVMS?
- DVMS nắm vững nhiều công nghệ phần mềm, mạng và viễn thông. Như Payment gateway, SMS gateway, GIS, VOIP, iOS, Android, Blackberry, Windows Phone, cloud computing,…
- DVMS có kinh nghiệm triển khai các hệ thống trên các nền tảng điện toán đám mây nổi tiếng như Google, Amazon, Microsoft,…
- DVMS có kinh nghiệm thực tế tư vấn, xây dựng, triển khai, chuyển giao, gia công các giải pháp phần mềm cho khách hàng Việt Nam, USA, Singapore, Germany, France, các tập đoàn của nước ngoài tại Việt Nam,…
Quý khách xem Hồ sơ năng lực của DVMS tại đây >>
Quý khách gửi yêu cầu tư vấn và báo giá tại đây >>