Ra mắt hai series mới cực hot Trí tuệ nhân tạo A đến ZPython công cụ không thể thiếu khi nghiên cứu Data science, Machine learning.

Forum dạng SPA với Laravel và Vue.js - Phần 2: Cơ bản về routing

Trong phần trước, chúng ta đã xây dựng xong khung dự án sử dụng cả Laravel và Vue.js, tiếp theo là các công việc khác, nó giúp hình thành dần dần ứng dụng Forum dạng ứng dụng đơn trang. Laravel cho phép tạo một master page để từ đó chúng ta có thể xây dựng các trang khác, với Vue.js và vue-router cũng vậy, chúng ta tạo ra một master view là App.Vue để từ đó có thể mở rộng ra các view (các Vue.component) khác.

1. Thiết kế master view App.vue

1.1 Tạo view chính App.vue

App.vue là khung chính cho view, từ đây có thể mở rộng ra các view khác trong ứng dụng, tạo file resources/assets/js/components/App.Vue với nội dung sau:

<template>
  <div id="root">
    <h1>
      SPA-FORUM <small> với Laravel + Vue.js</small>
    </h1>
    <router-view></router-view>
  </div>
</template>

Trong App.vue, thẻ là rất quan trọng nó nói với Vue.js rằng chỗ này sẽ được Vue-router xử lý và đưa vào các nội dung là các component tùy thuộc vào đường dẫn. Nó cũng giống như khi bạn làm việc với @yield trong Laravel template.

1.2 Thiết lập điểm bắt đầu của Vue.js

Nơi bắt đầu của Vue.js chính là resources/assets/js/app.js, thay đổi code như sau:

require('./bootstrap');

import Vue from 'vue';
import App from './components/App';

var vm = new Vue({
    el: '#app',
    render: h => h(App)
})

Một số chú ý, require('./bootstrap') là để tải file bootstrap.js, nội dung file này nhằm tải vào ứng dụng các thư viện cần thiết như jQuery, bootstrap sass, axios và thiết lập CSRF-Token một khái niệm trong Laravel. Tiếp đến là nó tải vào App component là master view cho ứng dụng, sau đó đến router là nơi thiết lập việc mapping giữa đường dẫn và các component để thực hiện render nội dung. ### 1.3 Thiết lập view mặc định của Laravel

Mọi ứng dụng Laravel đều được thiết lập đường dẫn trang chủ mapping với view resources/views/welcome.blade.php, chúng ta cần thay đổi nội dung view này để nó dùng các tài nguyên javascript, css đã được biên dịch.


<html lang="vi VN">
    <head>
        <meta charset="utf-8">
        <title>SPA Forum - Allaravel.com</title>

        <!-- Main styles for this application -->
        <link href="{{ mix('css/app.css') }}" rel="stylesheet">
        <meta id="csrf-token" name="csrf-token" value="{{ csrf_token() }}">
    </head>
    <body>
        <div id="app"></div>

        <script src="{{ mix('js/app.js') }}"></script>
    </body>
</html>

Ok, như vậy chúng ta đã thiết lập xong trang chính của dự án, chúng ta thử vào xem thế nào nhé. Nhớ chạy npm run watch để thực hiện biên dịch tài nguyên Javascript và CSS tự động ngay cả khi có thay đổi. Bạn chưa hiểu chỗ này xem thêm cách sử dụng Laravel Mix. Chú ý, để nguyên màn hình console này đừng tắt đi vì nó đang chạy liên tục.

Màn hình npm run watch

Ok, giờ chúng ta vào thử http://spa-forum.dev xem thế nào.

Màn hình chính của SPA Forum

2. Xây dựng nội dung con trong ứng dụng SPA-Forum

SPA-Forum đã có trang master, trong ứng dụng đa trang chúng ta có các trang khác nhau, với SPA các trang khác nhau là các nội dung khác nhau hay còn gọi là nội dung con. Chúng ta sẽ thực hiện xây dựng các nội dung con cho Category, Topic.

2.1 Cài đặt vue-router

Vue-router là gói thư viện giúp thực hiện tạo ra các nội dung bằng cách map giữa đường dẫn và các Vue component. (Tham khảo chi tiết về Vue-router). Thực hiện cài đặt gói Vue-router, do gói này không có trong thiết lập mặc định của Laravel Mix bằng lệnh npm install vue-router --save.

c:\xampp\htdocs\spa-forum>npm install vue-router --save
c:\xampp\htdocs\spa-forum
`-- vue-router@2.5.3

2.2 Xây dựng file mapping route

Thực tạo đưa hết các mapping giữa đường dẫn và Vue component vào file resources/assets/js/routes/index.js như sau:

import Vue from 'vue'
import Router from 'vue-router'

// Views
import HomeView from '../components/views/HomeView'
import CategoryView from '../components/views/CategoryView'
import TopicView from '../components/views/TopicView'

Vue.use(Router)

export default new Router({
  routes: [
    { path: '/', name: 'Home', component: HomeView },
    { path: '/category', name: 'Category', component: CategoryView },
    { path: '/topic', name: 'Topci', component: TopicView }
    ]
})

Trong này có một số chú ý, cần import Vue-router vào và sử dụng lệnh Vue.user(VueRouter) không sẽ bị lỗi hoặc không hoạt động được.

2.3 Tạo các Component cho nội dung con

Trong file mapping route đã có khai báo các component cho nội dung con chúng ta thực hiện tạo các component này trong resources/assets/js/components/views: HomeView.vue

<template>
  <div>
    Trang chủ
  </div>
</template>

CategoryView.vue

<template>
  <div>
    Trang Category
  </div>
</template>

TopicView.vue

<template>
  <div>
    Trang Topic
  </div>
</template>

Chúng ta thử thực hiện vào

Sẽ thấy các kết quả như sau:

Routing trong SPA Forum

3. Chế độ routing HTML5 history

Mặc định, vue-router sử dụng chế độ routing là hash, các đường dẫn sẽ có dạng http://spa-forum.dev/#/topic, http://spa-forum.dev/#/category... Vue-router cũng có một chế độ routing khác là HTML5 history, nó sử dụng history.pushState API để điều hướng các URL mà không cần tải lại trang. Do đó các đường dẫn trở lại về dạng như bình thường là http://spa-forum.dev/topic, http://spa-forum.dev/category. Chỉ cần thêm mode:'history' vào trong phần khai báo router là xong. Tuy nhiên, chúng ta sẽ gặp phải một vấn đề là khi thực thi http://spa-forum.dev/topic sẽ gặp lỗi như sau:

Lỗi khi chưa thiết lập route trong Laravel

Lỗi này do chúng ta chưa thiết lập các route của Laravel do khi chạy đường dẫn này thì máy chủ web Apache hoặc NginX sẽ đón nhận và xử lý routes/web.php mà hiện tại trong đây mới chỉ thiết lập đường dẫn trang chủ:

Route::get('/', function () {
    return view('welcome');
});

Để xử lý vấn đề này, chúng ta sẽ thiết lập để Laravel lắng nghe tất cả các request và định tuyến nó đến view welcome như sau:

Route::any('{all}', function () {
    return view('welcome');
})
->where(['all' => '.*']);

và nhường việc xử lý đường dẫn lại cho vue-router. Việc tiếp theo là chúng ta cần thiết lập mode history cho vue-router trong router/index.js:

import Vue from 'vue'
import Router from 'vue-router'

// Views
import HomeView from '../components/views/HomeView'
import CategoryView from '../components/views/CategoryView'
import TopicView from '../components/views/TopicView'

Vue.use(Router)

export default new Router({
    routes: [
    { path: '/', name: 'Home', component: HomeView },
    { path: '/category', name: 'Category', component: CategoryView },
    { path: '/topic', name: 'Topci', component: TopicView }
    ],
    mode: 'history'
})

4. Xử lý lỗi 404 trong Vue-router

Trong quá trình website vận hành, có nhiều đường link được copy từ website và dán vào đâu đó trên mạng như vào Facebook, vào các diễn đàn, vào các bài viết trong các trang tin... quá trình này có thể xảy ra lỗi copy không đầy đủ, dẫn đến các đường link không chạy được hoặc trang không tìm thấy. Các lỗi này gọi chung là lỗi 404 không tìm thấy trang web yêu cầu, trước đây chúng ta thường xử lý trong Laravel thông qua view được cài đặt sẵn là resources/views/error/404.blade.php. Lỗi 404 cũng có thể xử lý trong Vue-router rất đơn giản bằng cách thêm route sau vào routes/index.js

{ path: '*', component: NotFound }

Như vậy, khi xử lý qua các đường dẫn nếu đến cuối cùng mà vẫn không map được với component nào nó sẽ map với component NotFound.vue, chúng ta tạo ra một component NotFound.vue trong resources/components với nội dung tạm như sau:

<template>
  <div>
    Lỗi 404: Không tìm thấy trang yêu cầu
  </div>
</template>

Khi đó chúng ta thử thực hiện một đường dẫn ngẫu nhiên nào đó xem thế nào, ví dụ http://spa-forum.dev/tin-tuc/laravel-5-5-chuan-bi-ra-mat-trong-thang-7

Xử lý lỗi 404 trong SPA FOrum

Hoặc nếu bạn không thích tạo ra trang 404 thì bạn có thể chuyển hướng tất cả các trang không tồn tại về một trang nào đấy cũng được, ví dụ dưới đây chuyển hướng các trang không tìm thấy về trang chủ.

export default new Router({
  routes: [
    { path: '/', name: 'home', component: Home},
    { path: '/category', component: Category, name: 'category' }, 
    { path: '/topic', component: Topic, name: 'topic'}
  ],
    mode: 'history',
        redirect: {
                 '*' : '/'
        }
})

5. Tiếp theo sẽ làm gì?

Trong phần Cơ bản về routing này chúng ta đã tiếp tục xây dựng ứng dụng Forum đơn trang bằng Laravel và Vue.js, tóm lược lại các phần chúng ta đã xử lý như sau:

  • Xây dựng master view App.vue, làm quen với tạo ra các Vue component và map chúng với các route cụ thể.
  • Xử lý đường dẫn như đường dẫn bình thường với chế độ history.
  • Xử lý lỗi 404 không tìm thấy trang yêu cầu trong Vue-router.

Trong phần tiếp theo sẽ chuẩn bị các API cho category và topic, tiếp tục làm việc với từng đối tượng cụ thể trong ứng dụng như tạo database, viết các RESTful API mạnh mẽ và nhanh chóng.


CÁC BÀI VIẾT KHÁC

FirebirD

Đam mê Toán học, Lập trình. Sở thích chia sẻ kiến thức, Phim hài, Bóng đá, Cà phê sáng với bạn bè.

Forum dạng SPA với Laravel và Vue.js - Phần 1: Xây dựng khung dự án

Forum dạng SPA với Laravel và Vue.js - Phần 3: Xây dựng API

11 Bình luận trong "Forum dạng SPA với Laravel và Vue.js - Phần 2: Cơ bản về routing"

  1. Hoàng

    5 years ago

    Phản hồi
    Mình bị lỗi này: [Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option. found in ---> at C:\xampp\htdocs\directory\resources\assets\js\components\App.vue Đã thử install lại, thử cả CDN mà vẫn không hết.
    1. FirebirD

      5 years ago

      Phản hồi
      Có thể do bạn chưa đăng ký component, bạn paste nội dung của App.vue vào đây nhé
  2. VueError

    5 years ago

    Phản hồi
    Ad cho em hỏi em làm theo hướng dẫn và gặp lỗi "[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option." Ad có thể chỉ bảo giúp e không, e cảm ơn !
    1. FirebirD

      5 years ago

      Phản hồi
      Giống lỗi của bạn Hoàng ở trên, mình đoán là do bạn chưa import component mà đã sử dụng trong phần router, bạn có thể paste nội dung file mapping routes vào đây để mọi người xem và cùng debug nhé
      1. VueError

        5 years ago

        Phản hồi
        Cảm ơn add, hôm qua em tìm ra lỗi ở đâu rồi... Cần import file index.js vào app.js để khai báo router cho App.vue add ạ !!! Mong add sẽ có thêm nhiều bài viết cho anh em học tập he he...
  3. Error

    5 years ago

    Phản hồi
    Code in app.js if error require('./bootstrap'); import Vue from 'vue' import App from './components/App' import router from './routes/index.js' var vm = new Vue({ router, el: '#app', render: h => h(App) })
    1. Chiến

      5 years ago

      Phản hồi
      Được luôn. hehe
  4. tuandv

    5 years ago

    Phản hồi
    Có GIT của tutorial này không thế bác chủ? làm theo tutorial thì bug 1 đống luôn
  5. hai

    5 years ago

    Phản hồi
    Mình thêm mode: 'history' vào router ok rồi mà khi run http://spa-forum.dev/category chẳng thấy nó hiện thông tin component
    1. LW

      5 years ago

      Phản hồi
      Mình cũng bị tương tự
  6. Xuân Phượng

    3 years ago

    Phản hồi

    lỗi chưa improt component thôi bác

Thêm bình luận