Tự code chức năng phân trang bằng AJAX [NEW]

Kỹ thuật AJAX (Asynchronous JavaScript and XML) hiện nay đã quá phổ biến trên website, nó sẽ giúp truyền dữ liệu từ backend ra frontend mà không cần tải lại trang. Hàng ngày chắc hẳn bạn sẽ thấy nhiều ví dụ về cách sử dụng AJAX, như việc nhấn nút like hay gửi bình luận trên Facebook cũng là AJAX.

Trong bài viết này, tôi sẽ hướng dẫn bạn cách làm quen với các kỹ thuật AJAX áp dụng cho WordPress với ví dụ phổ biến nhất là phân trang AJAX. Từ ví dụ này, bạn có thể hiểu cách AJAX hoạt động trong WordPress để gửi dữ liệu đến front-end.

Nguồn tải xuống

Sử dụng chủ đề TwentyFifteen

Trong ví dụ này, tôi sẽ sử dụng chủ đề TwentyFifteen để bạn dễ theo dõi. Nhưng bạn vẫn có thể làm được ở các theme khác vì bạn chỉ cần tìm chọn link redirect mà thôi, nếu bạn tùy chỉnh từ theme khác thì nên tạo theme con.

Tự code chức năng phân trang bằng AJAX [NEW]

Tạo thư mục plugin

Bây giờ hãy vào thư mục / wp-content / plugins / và tạo một thư mục khác có tên ajax-pagination. Trong thư mục ajax-paginationbạn tạo một tệp có tên plugin.php với nội dung sau:


<?php
/*
Plugin Name: AJAX Pagination
Description: Phân trang website bằng AJAX
Version: 1.0
Author: Thach Pham
Author URI: https://thachpham.com
*/

Từ bây giờ, tất cả mã PHP của bạn sẽ được viết trong tệp plugin.php này. Sau đó, bạn có thể vào Plugins -> Plugins đã cài đặt và kích hoạt plugin này.

Nhúng tệp Javascript vào chủ đề

Khi làm việc với AJAX, chúng ta sẽ cần viết thêm một số Javascript, vì vậy chúng ta sẽ cần tạo một tệp .js trong plugin và sau đó viết mã để nó tự nhúng vào theme. Bây giờ hãy tạo một tệp có tên ajax-pagination.jssau đó ghi mã này vào tệp plugin.php để chèn tệp này vào theme bạn đang sử dụng một cách tự động thông qua chức năng wp_enqueue_script sau đó móc nó vào móc wp_enqueue_scripts để nó thực thi.


/*
@ ajax_pagination_scripts()
@ Nhúng file ajax-pagination.js vào theme
*/
add_action( ‘wp_enqueue_scripts’, ‘ajax_pagination_scripts’ );
function ajax_pagination_scripts() {

/*
* Chèn file ajax-pagination.js vào frontend
*/
wp_enqueue_script( ‘ajax-pagination-script’, plugins_url( ‘/ajax-pagination.js’, __FILE__ ),
array( ‘jquery’ )
);
}

Về cách hooks hoạt động wp_enqueue_scripts và chức năng wp_enqueue_script Tôi sẽ giải thích như thế nào trong một bài đăng khác. Nhưng trước hết bạn có thể hiểu rằng với đoạn trên nó sẽ tự động chèn một tệp ajax-pagination.js trong thư mục plugin hiện tại của nó nhờ chức năng plugins_url()giống cái array('jquery') có nghĩa là để WordPress hiểu script này sẽ sử dụng jQuery để tự động chèn vào theme và luôn tải sau jQuery để tránh lỗi.

Nếu bạn cần chèn nhiều tệp Javascript khác nhau, chỉ cần viết nhiều đoạn văn wp_enqueue_script() trong một hàm và móc nó vào một cái móc wp_enqueue_scripts là được.

Bây giờ vào trang web để kiểm tra mã nguồn HTML bên ngoài frontend của nó, tệp ajax-pagination.js đã được gọi như thế này.

ajax-pagination-finish-addcript

Tìm lớp phân trang và viết sự kiện cho AJAX

Sự kiện cho AJAX có nghĩa là một hành động mà chúng ta muốn dựa vào để kích hoạt việc gửi truy vấn, ở đây chúng ta sẽ sử dụng sự kiện nhấp chuột để gửi truy vấn khi một vị trí nhất định được nhấp vào. Và vị trí đó chúng ta sẽ xác định là liên kết bên trong thanh phân trang.

Bây giờ, hãy chuyển đến thanh phân trang, nhấp chuột phải vào liên kết và chọn Kiểm tra Phần tử (hoặc Firebug) để xem lựa chọn của khu vực đó, nó trông như thế này.

ajax-pagination -entyfifteen-pagination

Chú ý như trong hình, thanh phân trang sẽ nằm bên trong vùng chọn có lớp .nav-links. Sau đó, các liên kết nội bộ sẽ có lớp.page-numbers. Riêng link cho nút tiếp theo sẽ có nhiều lớp hơn .next. Vì vậy, để tạo sự kiện chính xác, chúng tôi sẽ thiết lập sự kiện nhấp chuột dựa trên thẻ trong lựa chọn .nav-links (Viết như .nav-links a).

Đầu tiên hãy ghi cái này vào tệp ajax-pagination.js để thiết lập sự kiện và kiểm tra nó.


// chắc chắn là đang sử dụng chế độ No Conflict của jQuery, sử dụng jQuery() thay vì $()
jQuery.noConflict();

// load sau khi website được tải xong
jQuery( document ).ready( function($) {

$(document).on ( ‘click’, ‘.nav-links a’, function( event ) {
event.preventDefault();
// kiểm tra event click
alert( "Bạn vừa click vào phân trang đấy!" );
} ) // end event

} );

Và bây giờ bạn thử bấm vào phân trang xem có thấy cảnh báo không, nếu thấy thì là thành công và xóa đoạn đi alert() trong mã.

Thử nghiệm sự kiện

Thử nghiệm sự kiện

Sử dụng AJAX trong WordPress

Theo mặc định, WordPress đã tích hợp sẵn các phương thức để xử lý dữ liệu với AJAX, vì vậy chúng ta chỉ cần gọi nó nếu chúng ta sử dụng nó. Để gọi nó, chúng tôi sẽ tiến hành gọi tệp admin-ajax.php có sẵn trong WordPress với mã sau (được đặt bên trong hàm ajax_pagination_scripts mà chúng tôi đã khai báo ở trên):


/*
* Gọi AJAX trong WordPress
*/
global $wp_query;
wp_localize_script( ‘ajax-pagination-script’, ‘ajax_object’, array(

// Các phương thức sẽ sử dụng
‘ajax_url’ => admin_url( ‘admin-ajax.php’ ),
‘query_vars’ => json_encode( $wp_query->query )

));

Hàm wp_localize_script() sẽ có tác dụng phát hiện và sử dụng một tập lệnh nhất định đã có trong mã nguồn WordPress vì tệp admin-ajax.php đã có sẵn nên không sử dụng wp_enqueue_script() như trên. Trong đó, ajax_object là đối tượng mà chúng ta sẽ sử dụng sau này trong tệp .js để định nghĩa đối tượng AJAX. Còn global $wp_query; là chúng tôi sẽ cung cấp cho đối tượng $wp_query toàn cầu để nó có thể được sử dụng trong tệp của plugin để lấy dữ liệu của bài đăng.

Sau khi chèn, bạn kiểm tra nguồn và sẽ thấy một đoạn script được in ra như sau:

[html]


[/html]

Bây giờ việc còn lại mà bạn cần làm trong bước này là viết Javascript để khai báo AJAX.


// chắc chắn là đang sử dụng chế độ No Conflict của jQuery, sử dụng jQuery() thay vì $()
jQuery.noConflict();

// load sau khi website được tải xong
jQuery( document ).ready( function($) {

$(document).on ( ‘click’, ‘.nav-links a’, function( event ) {
event.preventDefault();

// AJAX
$.ajax({
url: ajax_object.ajax_url,
type: ‘post’,
data: { action: ‘ajax_pagination_data’ },
success: function( ketqua ) {

// Thử nghiệm
var ketqua = "AJAX working";
alert( ketqua );

}

})
} ) // end event

} );

Từ đoạn 10 đến đoạn 23 là các mã mà chúng ta cần thêm vào tệp ajax-pagination.js, tôi giải thích như sau:

  • $.ajax() – Đây là một chức năng đặc biệt trong jQuery giúp cho việc xử lý AJAX trở nên đơn giản và gọn gàng hơn.
    • url: Đường dẫn của tệp mà dữ liệu sẽ được gửi đến khi thực thi AJAX từ sự kiện nhấp chuột. ajax_object.ajax_url có nghĩa là đường dẫn của tệp admin-ajax.php mà chúng tôi đã khai báo trong tệp plugin.php.
    • type: loại phương thức để gửi dữ liệu, sử dụng POST hoặc GET bất cứ điều gì bạn muốn, nhưng nếu nó chỉ nhận dữ liệu, tôi khuyên bạn nên sử dụng POST.
    • data: khai báo đối tượng chứa dữ liệu trả về sau khi gửi yêu cầu từ AJAX. ajax_pagination_data nghĩa là hàm trả về dữ liệu, chúng ta sẽ viết sau.
    • success: hành động sau khi truyền dữ liệu AJAX thành công, tạm thời ở đây sẽ kiểm tra bằng cách in một đoạn văn bản để kiểm tra. Nếu nó quay trở lại, thì thành công.

Bây giờ hãy lưu nó và thử nhấp vào liên kết phân trang để xem biến ketqua có trả về không, nếu có thì nó hoạt động.

ajax-pagination-test-ajax

Tạo một hàm trả về dữ liệu từ WordPress

Như tôi đã nói ở trên, tham số dữ liệu sẽ chứa đối tượng trả về, vì vậy bây giờ chúng ta sẽ xây dựng đối tượng ajax_pagination_data để trả về cho người dùng khi họ truyền dữ liệu. Trước tiên, bạn sẽ cần chỉnh sửa tệp ajax-pagination.js trở thành như sau:


// chắc chắn là đang sử dụng chế độ No Conflict của jQuery, sử dụng jQuery() thay vì $()
jQuery.noConflict();

// load sau khi website được tải xong
jQuery( document ).ready( function($) {

/*
@ hàm xác định số trang sẽ được tải
@ bằng cách bóc tách số trong chuỗi dữ liệu
*/
function set_page( element ) {
element.find(‘span’).remove();
return parseInt( element.html() );
}

$(document).on ( ‘click’, ‘.nav-links a’, function( event ) {
event.preventDefault();
page = set_page( $(this).clone() );

// AJAX
$.ajax({
url: ajax_object.ajax_url,
type: ‘post’,
data: {
action: ‘ajax_pagination_data’,
query_vars: ajax_object.query_vars,
page: page
},
beforeSend: function() {
/*
@ Tạo các hiệu ứng trước khi request gửi đi
*/
$( ‘#main’ ).find( ‘article’ ).remove();
$( ‘#main nav’ ).remove();
$( ‘#main’ ).scrollTop(0);
$( ‘#main’ ).append( ‘<div id="loading">Đang lấy dữ liệu bài viết</div>’ );
},
success: function( ketqua ) {
/*
@ Xóa nút loading
@ và khôi phục lại dữ liệu trả về
*/
$( ‘#main’ ).find( ‘#loading’ ).remove();
$( ‘#main’ ).append( ketqua );
console.log(page);

}

})
} ) // end event

} );

Trong mã mới, chúng ta có một hàm mới có tên set_page() trong Javascript. Hàm này sẽ có tác dụng tìm kiếm tất cả nội dung trong thẻ span của tài liệu. Sau đó tiến hành sử dụng chức năng parseInt() trong Javascript để tách số trong chuỗi dữ liệu được tìm thấy. Mục đích của nó là để chúng ta lấy số thứ tự của trang trong văn bản trên website, ví dụ trên thanh phân trang sẽ có các số 1,2,3,4,… thì sẽ lấy các số này làm giá trị của trang. Tham số trang là để giúp truy vấn WordPress hiểu trang nào sẽ lấy dữ liệu từ đó.

Chúng tôi sẽ khai báo nhiều tham số hơn query_varspage sẽ được sử dụng để gửi truy vấn trong WordPress để lấy danh sách các bài đăng. Thông số query_vars được coi như một phương thức của đối tượng ajax_object mà chúng tôi đã khai báo trong tệp plugin.php. Tham số trang là nó sẽ sử dụng giá trị trả về của hàm set_page () mà chúng ta đã tạo ở trên.

Tiếp theo là tham số beforeSend để thêm một cái gì đó trước khi dữ liệu của truy vấn được gửi đi. Chúng tôi sẽ sử dụng nó để xóa các bài đăng ( aritlce Trong #main của TwentyFifteen), hãy xóa thẻ khung phân trang hiện có (thẻ nav có lớp học pagination Trong #main của TwentyFifteen) và cuối cùng thêm dữ liệu đã nhận vào bên trong #main. Và quan trọng, tự động chuyển lên đầu trang web với scrollTop và in một đoạn văn bản cho người dùng biết rằng dữ liệu đang được tải.

Cuối cùng, tham số thành công sẽ trả về kết quả sau khi gửi truy vấn AJAX đến WordPress vì tham số ketqua mà WordPress tự hiểu là hàm thu thập dữ liệu trả về. Đồng thời xóa từ Lấy dữ liệu bài đăng khác.

Tôi cũng muốn lưu ý những điều sau:

  • #main – lựa chọn khung hiển thị danh sách các bài viết.
  • article – lựa chọn cá nhân của bài đăng, bạn cũng có thể sử dụng lớp .post.
  • nav.pagination – lựa chọn cho các khung phân trang.

Và tiếp theo là tạo một hàm trả về dữ liệu cho AJAX với hook là tên action wp_ajax_ajax_pagination_datatrong đó ajax_pagination là tên hành động mà chúng tôi đã khai báo trong ajax-pagination.js và wp_ajax là tiền tố bắt buộc cho hook khi làm việc với AJAX trong WordPress.


/*
@ Hàm chứa dữ liệu trả về
*/
add_action( ‘wp_ajax_nopriv_ajax_pagination_data’, ‘set_ajax_pagination_data’ );
add_action( ‘wp_ajax_ajax_pagination_data’, ‘set_ajax_pagination_data’ );
function set_ajax_pagination_data() {

$query_vars = json_decode( stripslashes( $_POST[‘query_vars’] ), true );

$query_vars[‘paged’] = $_POST[‘page’];

$posts = new WP_Query( $query_vars );
$GLOBALS[‘wp_query’] = $posts;

if( ! $posts->have_posts() ) {
get_template_part( ‘content’, ‘none’ );
}
else {
while ( $posts->have_posts() ) {
$posts->the_post();
get_template_part( ‘content’, get_post_format() );
}
}

the_posts_pagination( array(
‘mid_size’ => 5,
‘prev_text’ => __( ‘Previous page’, ‘twentyfifteen’ ),
‘next_text’ => __( ‘Next page’, ‘twentyfifteen’ ),
‘before_page_number’ => ‘<span class="meta-nav screen-reader-text">’ . __( ‘Page’, ‘twentyfifteen’ ) . ‘ </span>’,
) );

die();

}

Trong đoạn trên, trước tiên chúng ta truyền dữ liệu vào biến $_POST['query_vars'] được trả về bởi AJAX vì hàm mặc định $.ajax() của jQuery sẽ trả về dữ liệu dưới dạng JSON và lưu trữ nó trong một biến $query_vars.

Tiếp theo, chúng tôi đưa ra giá trị của $_POST['page'] khi được AJAX gửi lại vào biến $query_vars['paged'] để thiết lập phân trang cho truy vấn.

Cuối cùng, chúng tôi tạo một đối tượng $posts quay đi $query_vars ở trên và mẫu cuộc gọi content.php ra để hiển thị nội dung. Trong chủ đề TwentyFifteen, tệp này sẽ chứa mã hiển thị từng phần tử của bài đăng và vòng lặp tự lặp lại. Đồng thời chèn một thanh phân trang mới với chức năng the_posts_pagination() và kết thúc quá trình cho đến khi nó kết thúc vòng lặp.

Bây giờ bạn có thể lưu nó và đi ra ngoài và thử nhấp vào liên kết chuyển hướng trong các số trong phân trang để xem nó có hoạt động hay không, nếu bạn đã làm ngay từ đầu thì nó sẽ hoạt động.

Cũng cần lưu ý rằng từ WordPress 4.1 trở đi, hàm the_posts_pagination() sẽ hiển thị thanh phân trang số.

Các vấn đề gặp phải trong hướng dẫn này

Thực ra hướng dẫn này tôi đang gặp một vấn đề là nếu bạn nhấp vào liên kết số trên phân trang thì nó sẽ hoạt động, nhưng nếu bạn nhấp vào nút Tiếp theo hoặc tương tự như vậy nó trả về trang chủ. Bởi vì theo hướng dẫn này, dữ liệu từng trang của WordPress sẽ được truy xuất bởi biến $query_vars['paged'] mà nó lấy từ dữ liệu mà jQuery gửi lại bởi AJAX, trong khi trong tệp Javascript, tôi đã chỉ định rằng số trang sẽ được tìm thấy bằng cách sử dụng hàm parseInt() trong Javascript để tách số trên , là liên kết của mỗi trang trong phân trang. Nhưng nếu thẻ có dòng chữ Next, tất nhiên nó sẽ trả về giá trị “NaH”, tương ứng với không có dữ liệu số nên nó sẽ không hoạt động.

Còn về cách làm Next, Prev pagination thì hiện nay có rất nhiều bài hướng dẫn nên bạn có thể tìm kiếm trên Google.

Chúc may mắn!

5/5 – (1 phiếu bầu)