Single Page Application Concept Với Simple Demo (no framework)
Bài đăng này đã không được cập nhật trong 3 năm
Dạo gần đây có thể bạn nghe thấy một cái tên đang nổi trong xu hướng phát triển web - Single page application
. Mặc dù concept này đã ra đợi hơn chục năm nay. Cũng không ít website đã áp dụng kỹ thuật này.
Vậy nó là gì ? Tại sao nó lại trở thành xu hướng.
Bài viết này mình cùng tìm hiểu concept of Single Page Application
gọi tắt là SPA
với demo đơn giản, là xây dụng ứng dụng SPA với Javascript thuần ( no SPA framework).
Bài viết này chỉ focus vào concept of SPA, các đánh giá về performance, sử dụng loai dữ liệu truyển tải.. vv sẽ không được focus.
Concept
Hiểu một cách đơn giản, thì toàn bộ resource của web bao gồm các file CSS, Javascript, master layout hay cấu trúc web page sẽ được load lần đầu tiên khi chúng ta bắt đầu duyệt môt website A nào đó.
Ở những lần sau, khi chuyển trang khác, client sẽ gửi những ajax request để get dữ liệu cần thiết( thường là phần nội dung). Việc này mang đến trải nghiệm cho người dùng web tốt hơn, giảm thời gian phải load lại toàn bộ trang web cồng kềnh , tiết kiệm băng thông cũng như thời gian chờ đợi .
Việc quản lý và nhận biết điều hướng trang web có thể sử dụng location hash hoặc dựa vào HTML5 API với history state. Vì vậy mọi việc dường như đang được quản lý dưới client.
Việc này là trái ngược hoàn toàn với trang web truyền thống khi toàn bộ trang web phải load lại mỗi khi chuyển trang.
Để có cái nhìn dễ hiểu hơn, bạn hãy nhìn hình minh họa bên dưới về single page application
Vùng màu blue
được coi là khung hay master page của 1 website, vùng màu red
là content của web page sẽ hiển thị và thay thế mỗi khi chuyển trang.
Tất nhiên, đó cũng chỉ là một ví dụ đơn giản, không hẳn luôn luôn phải tạo 1 master page, Chúng ta có thể tùy biến theo từng giao diện theo từng yêu cầu của website.
Framework support
Hiện nay có khá nhiều Javascript framework support xây dựng SPA , nhưng nổi bật nhất theo xu hướng hiện nay đó là AngularJS và ReactJS.
Ngoài ra còn có VueJS, Backbone, Knockout ....
Việc sử dụng các framework sẽ giúp chúng ta quản lý router và các page dễ dàng hơn. Cũng như xây dựng lên cấu trúc web SPA. Để tìm hiểu kỹ hơn, bạn có thể tìm kiếm trên internet.
Phần dưới mình sẽ demo nhỏ về concept của SPA, mình sẽ sử dụng Javascript thuần (no SPA framework support) áp dụng kỹ thuật location hash #
để tạo nên một SPA concept.
Demo
Như phần đầu nội dung bài viết mình đã trao đổi :
"Bài viết này mình chỉ focus vào concept of SPA, các ý kiến về performance trong demo , các thức truyền tải data ..vv sẽ không được focus. Chúng ta có thể tùy biến data mà mình muốn"
Ngôn ngữ/libary sử dụng :
Frontend
: Javascript core + jQuery.Backend
: PHP with Yii2 MVC framework.
Một webpage đơn giản, có các menu với link sau :
- Dashboard :
<a href="#site/dashboard"> Dashboard </a>
- Orders :
<a href="#order"> Orders </a>
- News :
<a href="#news"> News </a>
- Setting :
<a href="#site/setting"> Setting </a>
Một vùng div
có id page-wrapper
hiển thị nội dung thay đổi của các page.
Trong một SPA thì việc handle chủ yếu thực hiện dưới client, vì vậy trong demo này bạn không cần hiểu rõ xây dựng backend như nào. Bạn chỉ cần hiểu rằng các request ajax mình gửi đi sẽ trả về HTML content của page tương ứng.
Mình tận dụng event hashchange
để nhận và sử dụng làm điều hướng giữa các trang.
Workflow như sau :
- Init event
hashchange
- Lấy phần #hash cũng chỉ là page URL để load HTML content của page đó.
- Request ajax để lấy HTML content sau đó append
html()
vào place holder vùng content trên master page.
Tạo router common
Tạo file main.js
và add event hashchange
:
$(document).ready(function () {
app.init();
app.load();
});
var app = {};
app.init = function () {
$(window).on('hashchange', function () {
// lấy location hash và execute ajax request để lấy html content
app.load();
});
}
Ai đã từng dùng jQuery chắc sẽ hiểu đoạn code trên làm gì. với app.init()
mình sẽ làm một vài việc khởi tạo cần làm trước tiên khi DOM đã được load.
Ở đây là việc lắng nghe location hash # thay đổi, để thực hiện load page theo #hash URL tương ứng.
Load html content
app.load = function () {
var router = window.location.hash.trim();
var url;
if (router == '') {
url = '/site/dashboard';
} else {
url = '/' + router.slice(1, router.length);
}
$.ajax({
url: url
}).done(function (data) {
document.title = $(data).find('.page-header').text();
$('#page-wrapper').html(data);
});
};
Mục đích đoạn code trên là lấy về location hash hiện tại :
- Nếu #hash không tồn tại : sẽ load home page là
site/dashboard
- Ngược lại : sẽ load theo hash #URL tương ứng
Một khi hoàn thành, nội dung get được sẽ được replace trong content view có id là page-wrapper
. Bạn để ý sẽ thấy cú pháp của jQuery : $('#page-wrapper').html(data);
Về cơ bản tư tưởng là vậy, nếu chúng ta sử dụng các framework support thì việc config router sẽ được clear hơn.
Chẳng hạn như config routing của Angular như bên dưới :
var app = angular.module("myApp", ["ngRoute"]);
app.config(function($routeProvider) {
$routeProvider
.when("/", {
templateUrl : "main.htm"
})
.when("/red", {
templateUrl : "red.htm"
})
.when("/green", {
templateUrl : "green.htm"
})
.when("/blue", {
templateUrl : "blue.htm"
});
});
Tổng kết
Viết thì dài, nhưng đúc kết lại như sau :
Với SPA, toàn bộ thành phần chính( như js, css , cấu trúc website...) sẽ được load lần được tiên khi chúng ta bắt đầu duyệt web hoặc khi F5(refresh) - giống như cách load 1 website thông thường vậy.
Trong quá trình duyệt web, mỗi khi switch giữa các pages, layout chúng ta sẽ chỉ lấy những dữ liệu cần thiết (JSON/HTML ...) dựa vào sự thay đổi của #location hash hoặc history state để nhận biết page
tương ứng. Bắng cách gửi những ajax request
theo để lấy data tương ứng.
Nếu sử dụng các SPA framework thì bạn không cần care điều này.
Link demo : http://spa-manhnv.ga/ Full Source code : https://github.com/manhnv118/single_page_application_js_core
All rights reserved