Code前端首页关于Code前端联系我们

1.Ziggy 和 Vue Router 分别是干啥的?

terry 7小时前 阅读数 11 #Vue
文章标签 Ziggy;Vue Router

想在 Laravel + Vue 的项目里让路由管理更省心?Ziggy 和 Vue Router 的组合能帮你解决前后端路由“各玩各的”的痛点,不少开发者碰到过改后端路由名,前端跳转链接得挨个改;或者前端路由参数和后端规则对不上,导致页面 404,其实把 Ziggy 的路由同步能力和 Vue Router 的前端路由管理结合起来,这些问题能一站式解决,下面从是什么、为什么、怎么用、实战案例到避坑,一步步讲清楚~

先聊 **Ziggy** —— 它是 Laravel 生态里的“路由翻译官”,Laravel 后端写路由时,会给路由起名字(`route('home')`),Ziggy 能把这些带名字的路由转换成前端能直接用的对象,包含路径、参数规则这些信息,打个比方,Laravel 里定义 `Route::get('/user/{id}', 'UserController@show')->name('user.show');`,Ziggy 能把这个路由变成前端可以调用的 `route('user.show', {id: 1})`,直接生成 `/user/1` 这样的链接,不用前端自己拼字符串。

再看 Vue Router —— 它是 Vue 单页面应用(SPA)的“导航管家”,前端不同页面(组件)之间跳转、传参、处理嵌套路由、设置页面标题这些,全靠 Vue Router 管,比如配置 const routes = [{ path: '/product', component: ProductList }],然后用 <router-link to="/product"> 或者 this.$router.push('/product') 实现跳转。

简单说,Ziggy 负责把后端 Laravel 的路由规则“搬运”到前端,Vue Router 负责前端内部的页面导航,两者结合,就能让前端用后端统一的路由命名和规则,不用自己维护一套路由列表。

为啥要把这俩工具绑一起?

(1)告别“硬编码路由”的痛苦

很多项目里,前端跳转链接是直接写死的,<a href="/user/123">,但如果后端路由改成 /profile/{id},前端所有写 /user/ 的地方都得改,漏一个就报错,用 Ziggy 的话,后端路由改名后,前端调用 route('user.profile', {id: 123}) 自动生成新路径,不用手动找遍代码改链接。

(2)前后端路由规则“说同一种话”

Laravel 路由可以设置参数验证、中间件这些,Ziggy 能把路由的参数名、可选参数这些信息同步到前端,Laravel 路由里 {id} 是必传参数,前端用 Ziggy 生成链接时如果没传 id,会直接报错提醒,避免前端传错参数导致 404,而且后端路由的命名(route('order.detail'))前端也能直接用,团队协作时前后端看同一个路由名,沟通成本低。

(3)大型项目开发效率翻倍

当项目有几十个页面、上百个路由时,前端单独维护 routes.js 文件特别麻烦,Ziggy 让前端不用自己写路由路径,直接复用后端定义的路由结构,比如新增一个“订单详情”页面,后端定义好 route('order.detail', ['order_id']),前端只用在 Vue Router 里配置组件,跳转时调用 route('order.detail', {order_id: 456}) 就行,不用关心路径是 /order/456 还是 /detail/order/456,后端改路径前端自动同步。

手把手教你集成 Ziggy + Vue Router

下面以 Laravel + Vue 3 + Vue Router 4 的项目为例,分后端、前端两步走:

(1)Laravel 端配置 Ziggy

首先用 Composer 装包:

composer require tightenco/ziggy

装完后,发布配置文件(可选,想自定义暴露哪些路由时用):

php artisan vendor:publish --tag=ziggy-config

打开 config/ziggy.php,可以设置 onlyexcept 来控制哪些路由暴露给前端,比如只暴露 web 路由里的:

'only' => ['home', 'user.*', 'product.show'], // 支持通配符,user 开头的所有路由

在 Blade 模板里(resources/views/app.blade.php),把 Ziggy 的路由信息输出到前端全局变量:

<script>
    window.route = @json(route()->all()); // 把所有路由信息给前端
</script>

如果是 SPA 项目,没有 Blade 模板,也可以写个 API 接口,返回 route()->all() 的内容,前端发请求获取。

(2)Vue 前端引入 Ziggy

先装前端包:

npm install @ziggy-js/vue

然后在 Vue 项目的入口文件(src/main.js)里注册 Ziggy 插件,并把后端的路由信息传进去:

import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import Ziggy from '@ziggy-js/vue'
import App from './App.vue'
// 假设从全局变量拿路由,或者从 API 请求后赋值
const routesData = window.route; // 对应 Blade 里输出的 route 对象
const app = createApp(App)
// 注册 Ziggy,传入路由数据
app.use(Ziggy, routesData)
// 配置 Vue Router
const router = createRouter({
    history: createWebHistory(),
    routes: [
        // 这里可以结合 Ziggy 的路由动态生成路径
        {
            name: 'user.show', // 和 Laravel 路由 name 一致
            path: route('user.show').path, // 用 Ziggy 的 route 函数获取路径
            component: () => import('./views/UserShow.vue')
        },
        // 其他路由...
    ]
})
app.use(router)
app.mount('#app')

(3)在组件里用 Ziggy 生成路由

组件里跳转可以直接用 Ziggy 的 route 函数,和 Vue Router 结合:

方式 1:用 <router-link> 组件

<template>
    <router-link :to="route('user.show', {id: 123})">
        查看用户 123 的资料
    </router-link>
</template>
<script setup>
import { route } from '@ziggy-js/vue' // 引入 route 函数
</script>

方式 2:编程式导航(比如点击按钮跳转)

<template>
    <button @click="goToProduct">查看商品</button>
</template>
<script setup>
import { route } from '@ziggy-js/vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const goToProduct = () => {
    const productSlug = 'iphone-15'
    router.push(route('product.show', {slug: productSlug}))
}
</script>

这样不管后端路由路径怎么改(比如从 /product/{slug} 改成 /p/{slug}),前端只要调用 route('product.show', {slug: ...}),路径会自动更新,不用改前端代码。

实战案例:电商项目的路由优化

拿“商品详情页 + 用户订单页”场景举例,看 Ziggy + Vue Router 怎么解决实际问题:

案例 1:商品详情页路由同步

后端 Laravel 路由:

Route::get('/products/{slug}', 'ProductController@show')->name('product.show');

前端原来的 Vue Router 配置(没结合 Ziggy 时):

{
    path: '/products/:slug',
    name: 'product.show',
    component: ProductShow
}

如果后端要把路径改成 /p/:slug,得同时改 Laravel 路由和 Vue Router 的 path,容易漏,用 Ziggy 后,Vue Router 的 path 可以动态获取:

{
    name: 'product.show',
    path: route('product.show').path, // 后端路由改了,这里自动变成 /p/:slug
    component: ProductShow
}

组件里跳转也更简单:

<router-link :to="route('product.show', {slug: product.slug})">
    {{ product.name }}
</router-link>

后端改路由路径后,前端不用改任何代码,Ziggy 自动同步新路径,避免人工失误。

案例 2:订单页的权限控制

后端 Laravel 路由加了中间件,只有登录用户能访问:

Route::get('/orders', 'OrderController@index')->name('order.index')->middleware('auth');

Ziggy 会把路由的 meta 信息(比如是否需要认证)同步到前端吗?其实可以自己扩展 Ziggy 的输出,在 Laravel 的 RouteServiceProvider 里给路由加 meta:

Route::get('/orders', 'OrderController@index')
    ->name('order.index')
    ->middleware('auth')
    ->metadata(['requiresAuth' => true]);

然后修改 Ziggy 的输出,把 metadata 带上(需要自定义 Ziggy 的生成逻辑,比如在 app/Providers/ZiggyServiceProvider.php 里):

public function boot()
{
    Ziggy::routes(function () {
        return Route::all()->map(function ($route) {
            return [
                'uri' => $route->uri,
                'name' => $route->getName(),
                'metadata' => $route->getMetadata(), // 把 metadata 加上
            ];
        });
    });
}

前端 Vue Router 的导航守卫里,就可以根据这个 metadata 判断是否需要登录:

router.beforeEach((to, from, next) => {
    const routeMeta = route(to.name).metadata // 用 Ziggy 获取路由的 metadata
    if (routeMeta?.requiresAuth && !isLoggedIn()) {
        next({ name: 'login' })
    } else {
        next()
    }
})

这样前后端的权限规则通过 Ziggy 同步,前端导航守卫和后端中间件逻辑一致,不用重复写权限判断。

避坑指南:这些问题要注意

(1)路由不同步,前端拿到的路由不是最新的

原因:Laravel 缓存了路由,或者前端没及时更新 Ziggy 的路由数据。
解决

  • 后端执行 php artisan route:cache 后,要确保 Ziggy 的路由也被更新,可重启服务或清除路由缓存后再生成 Ziggy 路由。
  • 前端若用 API 获取路由数据,要加版本号,或在后端路由变动时通知前端更新(比如发版时清前端缓存)。

(2)参数传递不匹配,生成的 URL 不对

原因:Ziggy 的 route 函数参数名和 Laravel 路由定义的参数名不一致。
Laravel 路由是 /user/{user_id},前端传 {id: 123},Ziggy 找不到对应参数,会把 id 当查询参数(变成 /user?user_id=123),导致 404。
解决:前端传参时,参数名必须和 Laravel 路由里的参数名完全一致,比如上面的情况要传 {user_id: 123}

(3)Vue Router 的 history 模式和 Laravel 路由冲突

原因:Vue Router 用 createWebHistory() 时,前端的 URL 是 /product/123,但 Laravel 没有对应的路由,会返回 404。
解决:Laravel 的 web.php 里加一个 fallback 路由,把所有前端路由指向 SPA 的入口:

Route::get('/{any}', function () {
    return view('app'); // 你的 SPA 入口模板
})->where('any', '.*');

Ziggy 生成的路由要和 Laravel 的 web 路由匹配,确保前端路由在 history 模式下能正确跳转,不会被 fallback 路由拦截。

最后总结一下:Ziggy 和 Vue Router 的组合,核心是让前后端路由“用同一份规则说话”,从减少硬编码错误,到提升团队协作效率,再到大型项目的可维护性,这套方案能解决很多实际开发中的痛点,只要把集成步骤吃透,避开参数、缓存、路由模式这些坑,就能让 Laravel + Vue 的项目路由管理变得丝滑起来~要是你在集成过程中碰到其他问题,比如和 Vue 2 版本的兼容,或者 Ziggy 的高级配置(比如多域名路由),可以留言讨论,咱们再深入拆解~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门