VueJS: Khớp route động
Thường thì ta cần map các route với mẫu đã cho tới cùng một component. Ví dụ ta có thể có component User
cần được được render cho tất cả người dùng nhưng với các ID người dùng khác nhau. Trong vue-router
ta có thể sử dụng phân đoạn động trong đường dẫn để đạt được điều đó:
const User = {
template: '<div>User</div>'
}
const router = new VueRouter({
routes: [
// các phân đoạn động bắt đầu bằng dấu :
{ path: '/user/:id', component: User }
]
})
Vậy thì những URL dạng như /user/foo
hay /user/bar
sẽ có thể được map thành cùng một route.
Phân đoạn động được biểu thị bằng dấu :. Khi một route nào đó khớp với phân đoạn động thì giá trị được hiển thi dưới dạng this.$route.params
trong mỗi component. Vậy nên ta có thể render ID người dùng hiện thời bằng cách update template của User
thành:
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
Trong một route ta được quyền có thể có nhiều phân đoạn động và chúng sẽ map tới các trường tương ứng trên $route.params
. Ví dụ:
pattern | matched path | $route.params |
---|---|---|
/user/:username | /user/evan | { username: 'evan' } |
/user/:username/post/:post_id | /user/evan/post/123 | { username: 'evan', post_id: '123' } |
Cùng với $route.params
thì đối tượng $route
cũng hiển thi các thông tin hữu ích khác như $route.query
(nếu có một truy vấn trong URL), $route.hash
, ...
Phản ứng với các thay đổi tham số
Một điều cần lưu ý là khi sử dụng các route với các param người dùng điều hướng /user/foo
thành /user/bar
, đó là cùng một component sẽ được tái sử dụng. Vì tất cả các routes đều render cùng một component nên điều này sẽ hiệu quả hơn so với việc hủy một đối tượng cũ để tạo đối tượng mới. Tuy vậy thì điều này cũng có nghĩa là các hook vòng đời của component sẽ không được gọi đến.
Để phản ứng với các tham số thay đổi ở cùng một component thì ta cần sử dụng watch với đối tượng $route
:
const User = {
template: '...',
watch: {
'$route' (to, from) {
// react to route changes...
}
}
}
Hoặc ta cũng có thể sử dụng bộ beforeRouteUpdate
:
const User = {
template: '...',
beforeRouteUpdate (to, from, next) {
// phản ứng với các thay đổi
// đừng quên gọi next()
}
}
Bắt tất cả các route / 404 không tìm thấy
Các tham số thông thường sẽ chỉ tương thích với các ký tự nằm giữa các đoạn của URL được phân cách bằng /
. Nếu ta muốn tương thích với tất cả thì ta sử dụng dấu *
:
{
// tương thích với tất cả
path: '*'
}
{
// khớp với tất cả bắt đầu là `/user-`
path: '/user-*'
}
Khi sử dụng các route * thì hãy đảm bảo rằng thứ tự các route cần đặt đúng trong đó các route * sẽ đặt ở cuối cùng. Route { path: '*' }
thường được dùng cho 404. Nếu ta sử dụng History mode thì hãy đảm bảo là cấu hình server phải chuẩn.
Khi sử dụng một * thì tham số có tên pathMatch
sẽ tự động được thêm vào $route.params
. Nó có chứa một phần của URL đã khớp với *:
// Cho route { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// Cho route { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'
Các mẫu khớp nâng cao
vue-router
sử dụng path-to-regexp làm công cụ khớp đường dẫn cho nó, cho nên nó hỗ trợ nhiều mẫu khớp nâng cao như các tùy chọn phần đoạn động, >=0, >=1, và cả các mẫu biểu thức chính quy tùy chỉnh. Hãy kiểm tra documentation với những mẫu nâng cao này và ví dụ này sử dụng chúng trong vue-router
.
Khớp theo thứ tự
Đôi khi một URL có thể được khớp bởi nhiều route. Trong trường hợp như vậy thì khớp theo thứ tự sẽ được xác định theo thứ từ của route đã định nghĩa: route được định nghĩa trước sẽ có thứ tự cao hơn.