前言
什麼是無限滾動?無限滾動是一種網頁設計技術,可在使用者滾動頁面時連續載入內容,從而無需分頁。
快速開始
使用 composer 安裝 laravel 專案
composer create-project laravel/laravel example-app
cd example-app
php artisan serve
接下來在瀏覽器訪問 http://127.0.0.1:8000
即可:
修改 .env 檔案
.
.
.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_database_username
DB_PASSWORD=your_database_password
.
.
.
建立模型控制器和遷移
我們可以使用以下命令快速生成 Model
、Controller
、Migration
、Factory
和 Seeder
檔案。
php artisan make:model Employee -cmfs
提示資訊:
Model created successfully.
Factory created successfully.
Created Migration: xxxx_xx_xx_xxxxxx_create_employees_table
Seeder created successfully.
Controller created successfully.
修改 Model 檔案
app\Models\Employee.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Employee extends Model
{
use HasFactory;
protected $fillable = [
'name',
'phone',
];
}
修改 Migration 檔案
database/migrations/xxxx_xx_xx_xxxxxx_create_employees_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateEmployeesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('employees', function (Blueprint $table) {
$table->id();
$table->string ( 'name' );
$table->string ( 'phone' );
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('employees');
}
}
修改 Factory 檔案
database/factories/EmployeeFactory.php
<?php
namespace Database\Factories;
use App\Models\Employee;
use Illuminate\Database\Eloquent\Factories\Factory;
class EmployeeFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Employee::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->name,
'phone' => $this->faker->phoneNumber,
];
}
}
修改 Seeder 檔案
database/seeders/EmployeeSeeder.php
<?php
namespace Database\Seeders;
use App\Models\Employee;
use Illuminate\Database\Seeder;
class EmployeeSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Employee::factory ( 333 )->create();
}
}
修改 DatabaseSeeder 檔案
database/seeders/DatabaseSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
// \App\Models\User::factory(10)->create();
$this->call ( EmployeeSeeder::class );
}
}
最後,執行一下遷移命令:
php artisan migrate --seed
提示資訊:
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (57.98ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (49.97ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (49.15ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated: 2019_12_14_000001_create_personal_access_tokens_table (79.26ms)
Migrating: 2021_10_10_151307_create_employees_table
Migrated: 2021_10_10_151307_create_employees_table (25.63ms)
Seeding: Database\Seeders\EmployeeSeeder
Seeded: Database\Seeders\EmployeeSeeder (128.42ms)
Database seeding completed successfully.
修改 Controller 檔案
app/Controllers/EmployeeController.php
<?php
namespace App\Http\Controllers;
use App\Models\Employee;
use Illuminate\Http\Request;
class EmployeeController extends Controller
{
public function index ( Request $request )
{
if ( $request->ajax() ) {
$employees = Employee::paginate ( 9 );
return response()->json ( [
'data' => $employees,
] );
}
return view ( 'employee.index' );
}
}
檢視檔案
在 resources/views
目錄下新建一個 employee
目錄,然後在 employee
新建 index.blade.php
檔案:
resources/views/index.blade.php
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Employees</title>
<!-- 引入 CSS 檔案 -->
<link rel ="stylesheet" href ="//cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<link rel="stylesheet" href="//cdn.materialdesignicons.com/5.4.55/css/materialdesignicons.min.css">
</head>
<body>
<div class="container">
<h3 class="text-center mb-5 mt-5">使用 Laravel8 + Ajax 無限分頁</h3>
<div class="row" id="app">
<!-- 由 Ajax 填充 -->
</div>
<div class="ajax-load text-center" style="display:none">
<i class="mdi mdi-48px mdi-spin mdi-loading"></i> 載入中...
</div>
<div class="no-data text-center mb-4" style="display:none">
<b>已經到底啦!</b>
</div>
</div>
<!-- 引入 JS 檔案 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
<script>
var pages = 2;
var currentPage = 0;
// boolean 是保留字,改程式碼的時候要注意。
var bool = false;
var lastPage;
$(window).scroll ( function () {
var height = $(document).height();
if ( $(window).scrollTop() + $(window).height() >= height && bool == false && lastPage > pages - 2 ) {
bool = true;
$('.ajax-load').show();
lazyLoad ( pages ).then ( () => {
bool = false;
pages ++;
if ( pages - 2 == lastPage ) {
$('.no-data').show();
}
} );
}
} );
function lazyLoad ( page ) {
return new Promise ( ( resolve, reject ) => {
$.ajax ( {
type: 'get',
url: '?page=' + page,
beforeSend () {
$('.ajax-load').show();
},
success: ( response ) => {
$('.ajax-load').hide();
var html = '';
for ( var i = 0; i < response.data.data.length; ++ i ) {
html += `
<div class="col-md-4 mb-3" >
<div class="card">
<div class="card-header">Employee Title</div>
<div class="card-body">
<table class="table">
<tr>
<th>Name</th>
<td>:</td>
<td>` + response.data.data [ i ].name + `</td>
</tr>
<tr>
<th>Phone</th>
<td>:</td>
<td>` + response.data.data [ i ].phone + `</td>
</tr>
</table>
</div>
</div>
</div>
`;
}
$('#app').append ( html );
resolve();
}
} );
} );
}
loadData(1);
function loadData ( page ) {
$.ajax ( {
type: 'get',
url: '?page=' + page,
beforeSend () {
$('.ajax-load').show();
},
success: ( response ) => {
$('.ajax-load').hide();
lastPage = response.data.last_page;
var html = '';
for ( var i = 0; i < response.data.data.length; ++ i ) {
html += `
<div class="col-md-4 mb-3" >
<div class="card">
<div class="card-header">Employee Title</div>
<div class="card-body">
<table class="table">
<tr>
<th>Name</th>
<td>:</td>
<td>` + response.data.data [ i ].name + `</td>
</tr>
<tr>
<th>Phone</th>
<td>:</td>
<td>` + response.data.data [ i ].phone + `</td>
</tr>
</table>
</div>
</div>
</div>
`;
}
$('#app').html ( html );
}
} );
}
</script>
</body>
</html>
修改路由檔案
在 web.php
檔案裡面新增一行路由:
routes/web.php
Route::get ( 'employees', [ EmployeeController::class, 'index' ] )->name ( 'employees.index' );
效果
最後在瀏覽器訪問 http://127.0.0.1:8000/employees
就可以看到效果了。
本作品採用《CC 協議》,轉載必須註明作者和本文連結